|
| 1 | +from django.shortcuts import get_object_or_404 |
1 | 2 | from django.utils.translation import gettext_lazy as _
|
| 3 | +from flags.state import flag_enabled, flag_state, get_flags |
| 4 | +from rest_framework import status |
2 | 5 | from rest_framework.response import Response
|
| 6 | +from rest_framework.viewsets import ModelViewSet |
3 | 7 |
|
4 |
| -from ansible_base.feature_flags.serializers import FeatureFlagSerializer |
| 8 | +from ansible_base.feature_flags.models import AAPFlag |
| 9 | +from ansible_base.feature_flags.serializers import FeatureFlagSerializer, OldFeatureFlagSerializer |
5 | 10 | from ansible_base.lib.utils.views.ansible_base import AnsibleBaseView
|
| 11 | +from ansible_base.lib.utils.views.django_app_api import AnsibleBaseDjangoAppApiView |
| 12 | +from ansible_base.lib.utils.views.permissions import IsSuperuserOrAuditor |
| 13 | +from ansible_base.rest_pagination import DefaultPaginator |
6 | 14 |
|
7 |
| -from .utils import get_django_flags |
| 15 | +from .utils import get_django_flags, is_boolean_str |
8 | 16 |
|
9 | 17 |
|
10 |
| -class FeatureFlagsStateListView(AnsibleBaseView): |
| 18 | +class FeatureFlagsStatesView(AnsibleBaseDjangoAppApiView, ModelViewSet): |
| 19 | + """ |
| 20 | + A view class for displaying feature flags states |
| 21 | + """ |
| 22 | + |
| 23 | + queryset = AAPFlag.objects.order_by('id') |
| 24 | + permission_classes = [IsSuperuserOrAuditor] |
| 25 | + http_method_names = ['get', 'head', 'options'] |
| 26 | + |
| 27 | + def list(self, request): |
| 28 | + paginator = DefaultPaginator() |
| 29 | + flags = get_flags() |
| 30 | + ret = [] |
| 31 | + for flag in flags: |
| 32 | + ret.append({"flag_name": flag, "flag_state": flag_state(flag)}) |
| 33 | + result_page = paginator.paginate_queryset(ret, request) |
| 34 | + return paginator.get_paginated_response(result_page) |
| 35 | + |
| 36 | + |
| 37 | +class FeatureFlagsView(AnsibleBaseDjangoAppApiView, ModelViewSet): |
11 | 38 | """
|
12 | 39 | A view class for displaying feature flags
|
13 | 40 | """
|
14 | 41 |
|
| 42 | + queryset = AAPFlag.objects.order_by('id') |
15 | 43 | serializer_class = FeatureFlagSerializer
|
| 44 | + permission_classes = [IsSuperuserOrAuditor] |
| 45 | + http_method_names = ['get', 'put', 'head', 'options'] |
| 46 | + |
| 47 | + def update(self, request, **kwargs): |
| 48 | + _feature_flag = self.get_object() |
| 49 | + value = request.data.get('value') |
| 50 | + if not value: |
| 51 | + return Response(status=status.HTTP_400_BAD_REQUEST, data={"details": "Invalid request object."}) |
| 52 | + |
| 53 | + # Disable runtime toggle if the feature flag feature is not enabled |
| 54 | + if not flag_enabled('FEATURE_FEATURE_FLAGS_ENABLED'): |
| 55 | + return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED, data={"details": "Runtime feature flags toggle is not enabled."}) |
| 56 | + |
| 57 | + feature_flag = get_object_or_404(AAPFlag, pk=_feature_flag.id) |
| 58 | + if feature_flag.toggle_type == 'install-time': |
| 59 | + return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED, data={"details": "Install-time feature flags cannot be toggled at run-time."}) |
| 60 | + if feature_flag.condition == "boolean" and not is_boolean_str(value): |
| 61 | + return Response(status=status.HTTP_400_BAD_REQUEST, data={"details": "Feature flag boolean conditional requires using boolean value."}) |
| 62 | + feature_flag.value = value |
| 63 | + feature_flag.save() |
| 64 | + |
| 65 | + return Response(self.get_serializer().to_representation(feature_flag)) |
| 66 | + |
| 67 | + |
| 68 | +# TODO: This can be removed after functionality is migrated over to new class |
| 69 | +class OldFeatureFlagsStateListView(AnsibleBaseView): |
| 70 | + """ |
| 71 | + A view class for displaying feature flags |
| 72 | + """ |
| 73 | + |
| 74 | + serializer_class = OldFeatureFlagSerializer |
16 | 75 | filter_backends = []
|
17 | 76 | name = _('Feature Flags')
|
18 | 77 | http_method_names = ['get', 'head']
|
19 | 78 |
|
20 | 79 | def get(self, request, format=None):
|
21 |
| - self.serializer = FeatureFlagSerializer() |
| 80 | + self.serializer = OldFeatureFlagSerializer() |
22 | 81 | return Response(self.serializer.to_representation())
|
23 | 82 |
|
24 | 83 | def get_queryset(self):
|
|
0 commit comments