def create(self, request, *args, **kwargs): model_name = self.queryset.model._meta.model_name app_name = self.queryset.model._meta.app_label perm = '{}.add_{}'.format(app_name, model_name) with transaction.atomic(): response = super(PublicProjectViewSet, self).create(request, *args, **kwargs) user = request.user obj = self.queryset.model.objects.get(pk=response.data['id']) project = get_project_for_object(Project, obj) # Delete the object if the user doesn't have the right permissions # to create this. The object may get created without checking for # permissions, since the viewset returns True if the user just has # the required role in any organisation. If the newly created # object is not a project, and the user doesn't have permissions to # create it, we delete the object. if obj != project and not (user.has_perm( 'rsr.view_project', project) and user.has_perm(perm, obj)): obj.delete() if obj.pk is None: raise exceptions.PermissionDenied elif project is not None: log_project_changes(request.user, project, obj, {}, 'added') delete_project_from_project_directory_cache(project.pk) project.schedule_iati_checks() return response
def update(self, request, *args, **kwargs): response = super(PublicProjectViewSet, self).update(request, *args, **kwargs) obj = self.get_object() project = get_project_for_object(Project, obj) if project is not None: log_project_changes(request.user, project, obj, request.data, 'changed') delete_project_from_project_directory_cache(project.pk) project.schedule_iati_checks() return response
def destroy(self, request, *args, **kwargs): obj = self.get_object() project = get_project_for_object(Project, obj) try: response = super(PublicProjectViewSet, self).destroy(request, *args, **kwargs) except ProtectedError: msg = _("{}s with updates cannot be deleted".format( self.queryset.model.__name__)) return Response(msg, status=status.HTTP_405_METHOD_NOT_ALLOWED) if project is not None: log_project_changes(request.user, project, obj, {}, 'deleted') delete_project_from_project_directory_cache(project.pk) project.schedule_iati_checks() return response
def project_roles(request, project_pk): user = request.user project = get_object_or_404(Project, pk=project_pk) if not (user.is_admin or user.is_superuser or is_reporting_org_admin(user, project)): raise PermissionDenied status = 200 if request.method == "PATCH": roles = request.data.get("roles", []) auth_groups = {role["role"] for role in roles} unknown_groups = auth_groups - set(settings.REQUIRED_AUTH_GROUPS) if unknown_groups: response = { "error": "Unknown groups: {}".format(",".join(unknown_groups)) } return Response(response, status=400) emails = {role["email"] for role in roles} unknown_users = emails - set( User.objects.filter(email__in=emails).values_list("email", flat=True)) if unknown_users: response = { "error": "Unknown users: {}".format(",".join(unknown_users)) } return Response(response, status=400) groups = {name: Group.objects.get(name=name) for name in auth_groups} users = {email: User.objects.get(email=email) for email in emails} new_roles = { Role(email=role['email'], role=role['role']) for role in roles } existing_roles = { Role(*role) for role in project.projectrole_set.values_list( "user__email", "group__name").distinct() } use_project_roles = request.data.get('use_project_roles', False) or bool(new_roles) with transaction.atomic(): # Set use_project_roles flag on the project if project.use_project_roles != use_project_roles: project.use_project_roles = use_project_roles project.save(update_fields=["use_project_roles"]) # Delete roles for project_role in existing_roles - new_roles: deleted_roles = ProjectRole.objects.filter( project=project, user__email=project_role.email, group__name=project_role.role, ) deleted_role = deleted_roles.first() deleted_roles.delete() if deleted_role: log_project_changes(request.user, project, deleted_role, {}, 'deleted') # Create roles created = [ ProjectRole( project=project, user=users[project_role.email], group=groups[project_role.role], ) for project_role in (new_roles - existing_roles) ] ProjectRole.objects.bulk_create(created) for role in created: log_project_changes(request.user, project, role, {}, 'added') if not project.use_project_roles: roles = [] organisations = OrganisationBasicSerializer( project.partners.distinct(), many=True).data else: roles = ProjectRoleSerializer(project.projectrole_set.distinct(), many=True).data organisations = [] response = { "use_project_roles": project.use_project_roles, "roles": roles, "organisations": organisations, "project": project_pk, } return Response(response, status=status)