예제 #1
0
def init_auditlog():
    """Init auditlog"""
    if settings.TX_DISABLE_AUDITLOG:
        return

    for config in models_config.get_all_configs(False):
        if config.auditlog_disable or (
                not config.is_trionyx_model
                and not config.has_config('auditlog_disable')):
            continue

        post_save.connect(log_add,
                          sender=config.model,
                          dispatch_uid=(log_add, config.model, post_save))
        pre_save.connect(log_change,
                         sender=config.model,
                         dispatch_uid=(log_change, config.model, pre_save))
        post_delete.connect(log_delete,
                            sender=config.model,
                            dispatch_uid=(log_delete, config.model,
                                          post_delete))

        @tabs.register(config.model,
                       code='history',
                       name=_('History'),
                       order=999)
        def layout(obj):
            return auditlog_layout(obj)
예제 #2
0
    def auto_generate_missing_tabs(self):
        """Auto generate tabs for models with no tabs"""
        for config in models_config.get_all_configs(False):
            model_alias = self.get_model_alias(config.model)
            if model_alias not in self.tabs:

                @self.register(model_alias, order=10)
                def general_layout(obj):
                    return Layout(
                        Column12(
                            Panel(
                                'info',
                                DescriptionList(*[
                                    f.name for f in models_config.get_config(
                                        obj).get_fields()
                                ]))))
예제 #3
0
    def auto_regiser_models(self):
        """Auto register all models"""
        # Load serializers
        for app in apps.get_app_configs():
            for module in ['serializers', 'api.serializers']:
                try:
                    import_module('{}.{}'.format(app.module.__package__,
                                                 module))
                except ImportError:
                    pass

        for config in models_config.get_all_configs():
            if config.api_disable:
                continue

            model = config.model
            basename = model._meta.object_name.lower()
            classname = model.__name__
            serializer = serializer_register.get(model)
            serializer = serializer if serializer else self.generate_model_serializer(
                model, config)

            if [
                    name for name, field in serializer().get_fields().items()
                    if not field.read_only
            ]:
                base_classes = (ModelViewSet, )
            else:
                base_classes = (mixins.RetrieveModelMixin,
                                mixins.ListModelMixin,
                                mixins.DestroyModelMixin, GenericViewSet)

            DynamicViewSet = type(classname, base_classes, {})
            DynamicViewSet.model = model
            DynamicViewSet.queryset = model.objects.get_queryset()
            DynamicViewSet.serializer_class = serializer
            DynamicViewSet.permission_classes = (
                ExtendedDjangoModelPermissions, )
            DynamicViewSet.ordering = ['pk']
            DynamicViewSet.schema = APIAutoSchema(
                tags=[config.get_verbose_name_plural()])

            self.register(self.get_model_prefix(model), DynamicViewSet,
                          basename)
예제 #4
0
    def handle_request(self, request):
        """Handle search"""
        models = []
        content_types = {}
        for config in models_config.get_all_configs(False):
            if config.disable_search_index or not config.global_search:
                continue

            # Check if user has view permission
            if not request.user.has_perm(
                    '{app_label}.view_{model_name}'.format(
                        app_label=config.app_label,
                        model_name=config.model_name,
                    ).lower()):
                continue

            models.append(config.model)
            content_type = ContentType.objects.get_for_model(
                config.model, False)
            content_types[content_type.id] = str(
                config.model._meta.verbose_name_plural)

        results = OrderedDict()
        for entry in watson.search(request.GET.get('search', ''),
                                   models=models)[:100]:
            if entry.content_type_id not in results:
                results[entry.content_type_id] = {
                    'name': content_types[entry.content_type_id],
                    'items': [],
                }

            if len(results[entry.content_type_id]['items']) <= 10:
                results[entry.content_type_id]['items'].append({
                    'url':
                    entry.url,
                    'title':
                    entry.title,
                    'description':
                    entry.description,
                })

        return list(results.values())
예제 #5
0
    def get_schema(self, *args, **kwargs):
        """Extend schema"""
        schema = super().get_schema(*args, **kwargs)
        schema['components'] = {
            'securitySchemes': {
                "Api token": {
                    "type":
                    "apiKey",
                    "name":
                    "Authorization",
                    "in":
                    "header",
                    "bearerFormat":
                    'Token',
                    'description':
                    """{}

    Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b""".format(
                        _('The key should be prefixed by the string literal **"Token"**, with whitespace separating the two strings. For example:'
                          ),  # noqa E501
                    ),
                },
            }
        }

        groups = defaultdict(list)
        for config in models_config.get_all_configs():
            if config.api_disable:
                continue

            group_name = str(config.app_config.verbose_name)
            groups[group_name].append(config.get_verbose_name_plural(True))
            groups[group_name].sort()

        # TODO for custom views: add user defined groups and add custom tag to existing group
        schema['x-tagGroups'] = [{
            'name': name,
            'tags': groups[name],
        } for name in sorted(groups)]

        return schema
예제 #6
0
    def get_data(self, request: HttpRequest, config: dict) -> List[dict]:
        """Get data for widget"""
        content_type_ids = [
            content_type.id
            for model, content_type in ContentType.objects.get_for_models(*[
                config.model for config in models_config.get_all_configs(False)
                if request.user.has_perm(
                    '{app_label}.view_{model_name}'.format(
                        app_label=config.app_label,
                        model_name=config.model_name,
                    ).lower())
            ]).items()
        ]

        logs = AuditLogEntry.objects.filter(
            content_type__in=content_type_ids).prefetch_related('user')
        show = config.get('show', 'all')
        if show != 'all':
            logs = logs.filter(user__isnull=show == 'system')

        return [
            {
                'user_full_name':
                log.user.get_full_name() if log.user else _('System'),
                'user_avatar':
                log.user.avatar.url
                if log.user and log.user.avatar else static('img/avatar.png'),
                'action':
                renderer.render_field(log, 'action'),
                'object':
                '({}) {}'.format(
                    str(log.content_type.model_class()._meta.verbose_name).
                    capitalize(),  # type: ignore
                    log.object_verbose_name),
                'object_url':
                log.content_object.get_absolute_url()
                if log.content_object else '',
                'created_at':
                renderer.render_field(log, 'created_at'),
            } for log in logs.order_by('-created_at')[:6]
        ]
예제 #7
0
    def __init__(self, *args, **kwargs):
        """Init form"""
        super().__init__(*args, **kwargs)

        from trionyx.widgets import widget_data, GraphWidget
        self.fields['source'].choices = [
            ('', '------'),
            *[(code, data['name'])
              for code, data in widget_data.get_all_data(GraphWidget).items()],
            ('__custom__', _('Custom'))
        ]

        content_type_map = ContentType.objects.get_for_models(
            *list(models_config.get_all_models(utils.get_current_user())))
        interval_fields = {}
        graph_fields = {}

        for config in models_config.get_all_configs():
            if config.model not in content_type_map:
                continue

            graph_fields[content_type_map[config.model].id] = [{
                'id':
                '__count__',
                'text':
                str(_('Count records')),
            }, *[{
                'id': field.name,
                'text': str(field.verbose_name)
            } for field in config.get_fields()
                 if config.get_field_type(field) in ['int', 'float']]]

            interval_fields[content_type_map[config.model].id] = [
                {
                    'id': field.name,
                    'text': str(field.verbose_name)
                } for field in config.get_fields(True)
                if config.get_field_type(field) in ['date', 'datetime']
            ]

        self.fields['model'].choices = [
            (content_type.id, model._meta.verbose_name.capitalize())
            for model, content_type in content_type_map.items()
        ]

        self.helper = FormHelper()
        self.helper.layout = Layout(
            'source',
            Depend([('source', r'__custom__')],
                   'icon',
                   Div(Div(
                       'model',
                       css_class="col-md-6",
                   ),
                       Div(
                           HtmlTemplate(
                               'widgets/forms/model_field.html', {
                                   'model_id': '#id_model',
                                   'label': _('Field'),
                                   'name': 'field',
                                   'fields': graph_fields,
                                   'value': self.initial.get('field'),
                               }),
                           css_class="col-md-6",
                       ),
                       css_class="row"),
                   Div(Div(
                       HtmlTemplate(
                           'widgets/forms/model_field.html', {
                               'model_id': '#id_model',
                               'label': _('Interval field'),
                               'name': 'interval_field',
                               'fields': interval_fields,
                               'value': self.initial.get('interval_field'),
                           }),
                       css_class="col-md-6",
                   ),
                       Div(
                           'interval_period',
                           css_class="col-md-6",
                       ),
                       css_class="row"),
                   Fieldset(
                       _('Filters'),
                       Filters('filters', content_type_input_id='id_model'),
                   ),
                   css_id='widget-custom-source'))