def filter_queryset(self, request, queryset, view): event_types = request.query_params.getlist('event_type') if event_types: queryset = queryset.filter(event_type__in=event_types) features = request.query_params.getlist('feature') if features: queryset = queryset.filter( event_type__in=expand_event_groups(features)) if 'scope' in request.query_params: field = core_serializers.GenericRelatedField( related_models=utils.get_loggable_models()) field._context = {'request': request} scope = field.to_internal_value(request.query_params['scope']) # Check permissions visible = scope._meta.model.get_permitted_objects(request.user) if not visible.filter(pk=scope.pk).exists(): return queryset.none() content_type = ContentType.objects.get_for_model(scope._meta.model) events = models.Feed.objects.filter( content_type=content_type, object_id=scope.id, ).values_list('event_id', flat=True) queryset = queryset.filter(id__in=events) elif not request.user.is_staff and not request.user.is_support: # If user is not staff nor support, he is allowed to see # events related to particular scope only. queryset = queryset.none() return queryset
def test_author_can_update_event_groups(self, hook): event_groups = self.valid_event_groups event_types = loggers.expand_event_groups(event_groups) self.client.force_authenticate(user=self.author) response = self.update_hook(hook, {'event_groups': event_groups}) self.assertEqual(response.data['event_groups'], set(event_groups)) self.assertEqual(response.data['event_types'], set(event_types))
def test_user_can_subscribe_to_event_groups(self): event_groups = self.valid_event_groups event_types = loggers.expand_event_groups(event_groups) self.client.force_authenticate(user=self.author) response = self.client.post(WebHookFactory.get_list_url(), data={ 'event_groups': event_groups, 'destination_url': 'http://example.com/' }) self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.data['event_groups'], set(event_groups)) self.assertEqual(response.data['event_types'], set(event_types))
def all_event_types(self): from waldur_core.logging import loggers self_types = set(self.event_types) try: hook_ct = ct_models.ContentType.objects.get_for_model(self) base_types = SystemNotification.objects.get( hook_content_type=hook_ct) except SystemNotification.DoesNotExist: return self_types else: return (self_types | set(loggers.expand_event_groups(base_types.event_groups)) | set(base_types.event_types))
def validate(self, attrs): if not self.instance and 'event_types' not in attrs and 'event_groups' not in attrs: raise serializers.ValidationError(_('Please specify list of event_types or event_groups.')) if 'event_groups' in attrs: events = list(attrs.get('event_types', [])) groups = list(attrs.get('event_groups', [])) events = sorted(set(loggers.expand_event_groups(groups)) | set(events)) attrs['event_types'] = events attrs['event_groups'] = groups elif 'event_types' in attrs: attrs['event_types'] = list(attrs['event_types']) return attrs
def filter_queryset(self, request, queryset, view): search_text = request.query_params.get( settings.api_settings.SEARCH_PARAM, '') must_terms = {} must_not_terms = {} should_terms = {} excluded_event_types = set() if 'event_type' in request.query_params: must_terms['event_type'] = request.query_params.getlist( 'event_type') if 'feature' in request.query_params: features = request.query_params.getlist('feature') must_terms['event_type'] = expand_event_groups(features) # Group events by features in order to prevent large HTTP GET request if 'exclude_features' in request.query_params: features = request.query_params.getlist('exclude_features') excluded_event_types.update(expand_event_groups(features)) if 'exclude_extra' in request.query_params: excluded_event_types.update(expand_event_groups(['update'])) if not django_settings.DEBUG: excluded_event_types.update(expand_event_groups(['debug_only'])) if excluded_event_types: must_not_terms['event_type'] = list(excluded_event_types) if 'user_username' in request.query_params: must_terms['user_username'] = [ request.query_params.get('user_username') ] if 'scope' in request.query_params: field = core_serializers.GenericRelatedField( related_models=utils.get_loggable_models()) field._context = {'request': request} obj = field.to_internal_value(request.query_params['scope']) # XXX: Ilja - disabling this hack and re-opening a ticket. Additional analysis is required for # a proper resolution # # XXX: hack to prevent leaking customer events # permitted_uuids = [uuid.hex for uuids in # obj.get_permitted_objects_uuids(request.user).values() for uuid in uuids] # if obj.uuid.hex not in permitted_uuids: # raise ValidationError('You do not have permission to view events for scope %s' # % request.query_params['scope']) for key, val in obj.filter_by_logged_object().items(): must_terms[format_raw_field(key)] = [val] elif 'scope_type' in request.query_params: choices = utils.get_scope_types_mapping() try: scope_type = choices[request.query_params['scope_type']] except KeyError: raise ValidationError( _('Scope type "%(value)s" is not valid. Has to be one from list: %(items)s.' ) % dict(value=request.query_params['scope_type'], items=', '.join(choices.keys()))) else: permitted_items = scope_type.get_permitted_objects_uuids( request.user).items() if not permitted_items: return EmptyQueryset() for field, uuids in permitted_items: must_terms[field] = [uuid.hex for uuid in uuids] elif 'resource_type' in request.query_params and 'resource_uuid' in request.query_params: # Filter events by resource type and uuid. # Please note, that permission checks are skipped, # because we can't check permission for deleted resources. # Also note, that resource type validation is skipped as well, # because resource type name formatting is defined in structure application, # but we don't want to create circular dependency between logging and structure apps. # This issue could be fixed by switching resource type name formatting to str(model._meta) # as it is done for scope_type parameter validation. must_terms[format_raw_field('resource_type')] = [ request.query_params['resource_type'] ] must_terms[format_raw_field('resource_uuid')] = [ request.query_params['resource_uuid'] ] else: should_terms.update( event_logger.get_permitted_objects_uuids(request.user)) mapped = { 'start': request.query_params.get('from'), 'end': request.query_params.get('to'), } timestamp_interval_serializer = core_serializers.TimestampIntervalSerializer( data={k: v for k, v in mapped.items() if v}) timestamp_interval_serializer.is_valid(raise_exception=True) filter_data = timestamp_interval_serializer.get_filter_data() queryset = queryset.filter(search_text=search_text, should_terms=should_terms, must_terms=must_terms, must_not_terms=must_not_terms, start=filter_data.get('start'), end=filter_data.get('end')) order_by = request.query_params.get('o', '-@timestamp') if order_by: queryset = queryset.order_by(order_by) return queryset