示例#1
0
    def post(self, request, *args, **kwargs):
        job = get_object_or_404(
            Job,
            id=kwargs[self.job_id_url_kwarg],
            type_id=_DeletorType.id,
        )

        if job.user != request.user:
            raise PermissionDenied('You can only terminate your deletion jobs.')

        if not job.is_finished:
            raise ConflictError('A non finished job cannot be terminated.')

        jresult = JobResult.objects.filter(job=job).first()

        if jresult is not None:
            messages = jresult.messages

            raise ConflictError(
                gettext('Error. Please contact your administrator.')
                if messages is None else
                '\n'.join(messages)
            )

        job.delete()

        return HttpResponse()
示例#2
0
    def check_rfield(self, rfield, report):
        if rfield.report_id != report.id:  # NB: compare IDs to avoid a query
            raise ConflictError('This Field & this Report do not match.')

        if not rfield.sub_report_id:
            raise ConflictError(
                'This Field has no Report, so can no be (un)selected')
示例#3
0
def set_selected(request):
    POST = request.POST
    field_id = get_from_POST_or_404(POST, 'field_id', cast=int)
    report_id = get_from_POST_or_404(POST, 'report_id', cast=int)

    try:
        checked = bool(int(POST.get('checked', 0)))
    except ValueError:
        checked = False

    with atomic():
        report = get_object_or_404(Report.objects.select_for_update(),
                                   id=report_id)
        request.user.has_perm_to_change_or_die(report)

        rfield = get_object_or_404(Field, id=field_id)

        if rfield.report_id != report.id:
            raise ConflictError('This Field & this Report do not match.')

        if not rfield.sub_report_id:
            raise ConflictError(
                'This Field has no Report, so can no be (un)selected')

        report = rfield.report

        if rfield.selected != checked:
            if checked:  # Only one Field should be selected
                report.fields.exclude(pk=rfield.pk).update(selected=False)

            rfield.selected = checked
            rfield.save()

    return HttpResponse()
示例#4
0
    def check_instance_permissions(self, instance, user):
        if not instance.is_custom:
            raise ConflictError(
                gettext('You cannot delete this calendar: it is not custom.'))

        if instance.user_id != user.id:
            raise PermissionDenied(
                gettext('You are not allowed to delete this calendar.'))

        if not Calendar.objects.filter(user=user).exclude(
                id=instance.id).exists():
            raise ConflictError(
                gettext('You cannot delete your last calendar.'))

        ctype = ContentType.objects.get_for_model(Calendar)
        dcom = DeletionCommand.objects.filter(content_type=ctype).first()

        if dcom is not None:
            if dcom.job.status == Job.STATUS_OK:
                dcom.job.delete()
            else:
                # TODO: if STATUS_ERROR, show a popup with the errors ?
                raise ConflictError(
                    gettext(
                        'A deletion process for an instance of «{model}» already exists.'
                    ).format(model=ctype))
示例#5
0
    def get_form_class(self):
        creator = self.get_model_conf().creator

        if not creator.enable_func(user=self.request.user):
            raise ConflictError('This model has been disabled for creation.')

        if creator.url_name is not None:
            raise ConflictError('This model does not use this creation view.')

        return creator.form_class
示例#6
0
    def get_form_class(self):
        deletor = self.get_model_conf().deletor

        if not deletor.enable_func(instance=self.object, user=self.request.user):
            raise ConflictError('This model has been disabled for deletion.')

        if deletor.url_name is not None:
            raise ConflictError('This model does not use this deletion view.')

        return deletor.form_class
示例#7
0
    def get_linkable_ctypes(self):
        rfield = self.object

        hand = rfield.hand
        if hand is None:
            raise ConflictError(
                'This field is invalid')  # TODO: force brick to reload

        ctypes = rfield.hand.get_linkable_ctypes()
        if ctypes is None:
            raise ConflictError('This field is not linkable')

        return ctypes
示例#8
0
    def check_instance_permissions(self, instance, user):
        if instance.custom_field.is_deleted:
            raise ConflictError(gettext('This custom field is deleted.'))

        dcom = DeletionCommand.objects.filter(
            content_type=ContentType.objects.get_for_model(
                type(instance)), ).first()

        if dcom is not None:
            if dcom.job.status == Job.STATUS_OK:
                dcom.job.delete()
            else:
                # TODO: if STATUS_ERROR, show a popup with the errors ?
                raise ConflictError(
                    gettext('A deletion process for a choice already exists.'))
示例#9
0
    def post(self, request, **kwargs):
        user_id = self.kwargs[self.user_id_url_kwarg]
        user = request.user

        if int(user_id) == user.id:
            raise ConflictError(
                gettext("You can't deactivate the current user."))

        with atomic():
            user_to_deactivate = get_object_or_404(
                get_user_model().objects.select_for_update(),
                id=user_id,
            )

            if user_to_deactivate.is_staff and not user.is_staff:
                return HttpResponse(
                    gettext("You can't deactivate a staff user."),
                    status=400,
                )

            if user_to_deactivate.is_active:
                user_to_deactivate.is_active = False
                user_to_deactivate.save()

        return HttpResponse()
示例#10
0
    def get_group_id(self):
        group_id = int(self.kwargs[self.group_id_url_kwarg])

        if group_id >= len(self.get_groups()):
            raise ConflictError(f'The group ID "{group_id}" is invalid.')

        return group_id
示例#11
0
    def post(self, request, *args, **kwargs):
        target = get_from_POST_or_404(request.POST,
                                      self.target_order_arg,
                                      cast=int)

        self.object = cfci = self.get_cfci_for_update()
        desc = self.get_customform_descriptor()
        group_id = self.get_group_id()

        groups = [*self.get_groups()]
        if target > len(groups):
            raise ConflictError(f'The target "{target}" is too big.')

        moved_group = groups.pop(group_id)
        groups.insert(target, moved_group)

        cfci.store_groups(
            FieldGroupList(
                model=desc.model,
                groups=groups,
                cell_registry=desc.build_cell_registry(),
            ))
        cfci.save()  # TODO: only if changed ?

        return HttpResponse()
示例#12
0
    def post(self, request, *args, **kwargs):
        layout = get_from_POST_or_404(request.POST, self.layout_arg)
        if layout not in LAYOUTS:
            raise ConflictError(f'The layout "{layout}" is invalid.')

        self.object = cfci = self.get_cfci_for_update()
        desc = self.get_customform_descriptor()
        group_id = self.get_group_id()

        # groups = [
        #     FieldGroup(name=group.name, cells=group.cells, layout=layout)
        #     if i == group_id else
        #     group
        #     for i, group in enumerate(self.get_groups())
        # ]
        groups = [*self.get_groups()]
        groups[group_id]._layout = layout

        cfci.store_groups(
            FieldGroupList(
                model=desc.model,
                groups=groups,
                cell_registry=desc.build_cell_registry(),
            ))
        cfci.save()  # TODO: only if changed ?

        return HttpResponse()
示例#13
0
    def get_group(self):
        group = self.get_groups()[self.get_group_id()]

        if isinstance(group, ExtraFieldGroup):
            raise ConflictError('An extra group cannot be edited.')

        return group
示例#14
0
    def get_relation_types(self):
        subject = self.get_related_entity()
        subject_ctype = subject.entity_type
        rtypes = []
        subjects_prop_ids = None  # TODO: lazy object

        for rtype in RelationType.objects.filter(id__in=bricks.MailsHistoryBrick
                                                              .relation_type_deps):
            if not rtype.is_compatible(subject_ctype):
                continue

            # TODO: unit test
            # TODO: factorise with RelationsAdding
            needed_property_types = [*rtype.subject_properties.all()]
            if needed_property_types:
                if subjects_prop_ids is None:
                    subjects_prop_ids = {*subject.properties.values_list('type', flat=True)}

                if any(needed_ptype.id not in subjects_prop_ids
                           for needed_ptype in needed_property_types
                      ):
                    continue

            rtypes.append(rtype.id)

        # TODO: unit test
        if not rtypes:
            raise ConflictError(gettext('No type of relationship is compatible.'))

        return rtypes
示例#15
0
    def check_related_entity_permissions(self, entity, user):
        user.has_perm_to_view_or_die(entity)

        # TODO: move to EntityRelatedMixin ??
        if entity.is_deleted:
            raise ConflictError(
                'This entity cannot be converted because it is deleted.')
示例#16
0
    def get_form_class(self):
        form_class = self.forms_registry.get_form(self.get_created_model())

        if form_class is None:
            raise ConflictError('This type of resource has no quick form.')

        return form_class
示例#17
0
    def get_target_order(self):
        """Returns the future order (starting at 1) of the instance we want to move."""
        order = get_from_POST_or_404(self.request.POST, self.target_order_post_argument, int)
        if order < 1:
            raise ConflictError('Target order must be greater than or equal to 1.')

        return order
示例#18
0
    def check_related_ctype(self, ctype):
        self.request.user.has_perm_to_access_or_die(ctype.app_label)

        model = ctype.model_class()
        if not issubclass(model, CremeEntity):
            raise ConflictError(
                'This model is not a entity model: {}'.format(model))
示例#19
0
def search_person(request):
    search = get_from_GET_or_404(request.GET, 'search')

    if len(search) < 3:
        raise ConflictError(
            _('Your search is too short.'))  # TODO: client-side validation

    # TODO: populate employers
    contacts = EntityCredentials.filter(
        request.user,
        Contact.objects.exclude(is_deleted=True).filter(
            Q(first_name__icontains=search) | Q(last_name__icontains=search)
            | Q(
                relations__type__in=(
                    persons_constants.REL_SUB_EMPLOYED_BY,
                    persons_constants.REL_SUB_MANAGES,
                ),
                relations__object_entity__header_filter_search_field__icontains
                =search,
            )).distinct())[:30]

    orgas = EntityCredentials.filter(
        request.user,
        Organisation.objects.exclude(is_deleted=True).filter(
            name__icontains=search))[:30]

    return render(
        request, 'mobile/search.html', {
            'search': search,
            'contacts': contacts,
            'contact_model': Contact,
            'organisations': orgas,
            'orga_model': Organisation,
        })
示例#20
0
 def _get_task(self):
     try:
         return Relation.objects.get(subject_entity=self.instance.pk, type=REL_SUB_LINKED_2_PTASK) \
                        .object_entity \
                        .get_real_entity()
     except Relation.DoesNotExist as e:
         raise ConflictError('This Activity is not related to a project task.') from e
示例#21
0
    def export(self, entity, user):
        template = get_template(self.template_path)

        with override(language=self.flavour.language):
            html = template.render(self.get_context_data(object=entity))

        # response = HttpResponse(content_type='application/pdf')
        # response['Content-Disposition'] = \
        #     f'attachment; filename="{entity._meta.verbose_name}.pdf"'
        response = HttpResponse(
            headers={
                'Content-Type':
                'application/pdf',
                'Content-Disposition':
                f'attachment; filename="{entity._meta.verbose_name}.pdf"',
            })

        pisa_status = pisa.CreatePDF(
            html,
            dest=response,
            # TODO ? see https://xhtml2pdf.readthedocs.io/en/latest/usage.html#using-xhtml2pdf-in-django  # NOQA
            # link_callback=link_callback,
        )

        if pisa_status.err:
            # TODO: test ; use pisa_status.log ?
            raise ConflictError(
                _('An error happened while generating the PDF file.'))

        return response
示例#22
0
    def get_queryset(self):
        qs = self.model._default_manager.all()
        cursed_items = self.filter_non_exportable_items(qs)

        if cursed_items:
            ctypes = {bdl.content_type for bdl in cursed_items}
            try:
                ctypes.remove(None)
            except KeyError:
                default_config = False
            else:
                default_config = True

            ct_labels = sorted((str(ct) for ct in ctypes), key=collator.sort_key)

            if default_config:
                ct_labels.insert(0, _('Default configuration'))

            raise ConflictError(
                _(
                    'The configuration of blocks for detailed-views cannot be '
                    'exported because it contains references to some '
                    'instance-blocks ({blocks}), which are not managed, for the '
                    'following cases: {models}.'
                ).format(
                    blocks=self.items_to_str(cursed_items),
                    models=', '.join(ct_labels)
                )
            )

        return qs
示例#23
0
    def get_graph_data(self, request, order):
        brick_item = self.get_instance_brick_item()
        entity = self.get_related_entity()
        brick = brick_registry.get_brick_4_instance(brick_item, entity=entity)

        try:
            fetcher = brick.fetcher
        except AttributeError as e:
            raise ConflictError('Invalid brick: {e}') from e  # TODO: test

        try:
            x, y = fetcher.fetch_4_entity(
                entity=entity,
                order=order,
                user=request.user,
            )
        except (GraphFetcher.IncompatibleContentType,
                GraphFetcher.UselessResult):
            logger.exception(
                'Fetching error in %s.get_graph_data()',
                type(self).__name__,
            )
            x = y = None

        return fetcher.graph, x, y
示例#24
0
def delete_user_calendar(request):
    calendar = get_object_or_404(Calendar,
                                 pk=get_from_POST_or_404(request.POST, 'id'))
    user = request.user

    # TODO: factorise calendar credentials functions ?
    if not calendar.is_custom or (not user.is_superuser
                                  and calendar.user_id != user.id):
        raise PermissionDenied(
            ugettext('You are not allowed to delete this calendar.'))

    # Attach all existing activities to the default calendar
    replacement_calendar = Calendar.get_user_default_calendar(user)
    if replacement_calendar == calendar:
        replacement_calendar = Calendar.objects.filter(user=user)\
                                               .exclude(id=calendar.id)\
                                               .order_by('id')\
                                               .first()

        if replacement_calendar is None:
            raise ConflictError(
                ugettext('You cannot delete your last calendar.'))

    for activity in calendar.activity_set.all():
        activity.calendars.add(replacement_calendar)

    calendar.delete()
示例#25
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # TODO: should be in the view ?
        field_name = self.field_name
        if FieldsConfig.get_4_model(self._entity.__class__).is_fieldname_hidden(field_name):
            raise ConflictError('"{}" is hidden & so it cannot be edited'.format(field_name))
示例#26
0
    def check_related_entity_permissions(self, entity, user):
        super().check_related_entity_permissions(entity=entity, user=user)

        if not entity.is_alive():
            raise ConflictError(gettext("You can't add a resource or a working "
                                        "period to a task which has status «{}»"
                                       ).format(entity.tstatus.name)
                               )
示例#27
0
    def get_customform_descriptor(self):
        desc = super().get_customform_descriptor()

        if not next(desc.extra_group_classes, None):
            raise ConflictError(
                'This custom-form does not propose extra group.')

        return desc
示例#28
0
 def perform_deletion(self, request):
     try:
         get_object_or_404(
             self.model,
             pk=get_from_POST_or_404(request.POST, self.id_arg),
         ).delete()
     except ProtectedError as e:
         raise ConflictError(e.args[0])
示例#29
0
 def __init__(self, *args, **kwargs):
     # super(FieldConfigWizard._ModelStep, self).__init__(*args, **kwargs)
     super().__init__(*args, **kwargs)
     if not self.ctypes:
         raise ConflictError(
             ugettext(
                 'All configurable types of resource are already configured.'
             ))
示例#30
0
文件: mail.py 项目: mrjmad/creme_crm
 def get_email_ids(self, request):
     try:
         return [
             int(s) for s in get_from_POST_or_404(
                 request.POST, self.email_ids_arg).split(',') if s.strip()
         ]
     except ValueError as e:
         raise ConflictError(str(e)) from e