class APNSConfigSerializer(HyperlinkedMixin, ModelSerializer): APNS_VALIDATORS = [ ContentTypeValidator(('application/x-pkcs12', )), FileSizeValidator(209712) # 200kb ] PRODUCTION_VALIDATORS = APNS_VALIDATORS + [APNSCertificateValidator('Production')] DEVELOPMENT_VALIDATORS = APNS_VALIDATORS + [APNSCertificateValidator('Development')] hyperlinks = ( ('self', 'apns-config', ('instance.name',)), ('remove_certificate', 'apns-remove-certificate', ('instance.name',)), ) production_certificate = FileField(validators=PRODUCTION_VALIDATORS, required=False) development_certificate = FileField(validators=DEVELOPMENT_VALIDATORS, required=False) class Meta: model = APNSConfig fields = ( 'production_certificate_name', 'production_certificate', 'production_bundle_identifier', 'production_expiration_date', 'development_certificate_name', 'development_certificate', 'development_bundle_identifier', 'development_expiration_date' ) read_only_fields = ( 'production_expiration_date', 'development_expiration_date' ) def to_internal_value(self, data): ret = super().to_internal_value(data) production_certificate = ret.get('production_certificate') development_certificate = ret.get('development_certificate') if production_certificate: ret['production_certificate'] = production_certificate.read() if development_certificate: ret['development_certificate'] = development_certificate.read() return ret def to_representation(self, instance): ret = super().to_representation(instance) ret['production_certificate'] = bool(instance.production_certificate) ret['development_certificate'] = bool(instance.development_certificate) return ret
class FileSerializer(serializers.ModelSerializer): """ This serializer allows uploading a file in the ai-django-fileupload pattern Use like this (example for a ModelViewSet: @detail_route(methods=['post'], parser_classes=(MultiPartParser,)) def attach(self, request, pk=None): order = self.get_object() serializer = self.get_serializer(order, data=request.data) if serializer.is_valid(): serializer.save() return Response({'status': _('Die Datei wurde erfolgreich hochgeladen.')}) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) """ file = FileField(max_length=10 * 1024, allow_empty_file=False, help_text='The file with a size of up to 10 MB') class Meta: model = Attachment fields = ('file', ) def validate(self, validated_data): validated_data['content_type'] = ContentType.objects.get_for_model( self.instance) validated_data['object_id'] = self.instance.pk return validated_data def update(self, instance, validated_data): return Attachment.objects.create(**validated_data)
class BlobSerializer(DocumentSerializer): """ Blob serializer """ blob = FileField(write_only=True) handle = SerializerMethodField() upload_date = SerializerMethodField() class Meta: model = Blob fields = ['id', 'user_id', 'filename', 'handle', 'blob', 'upload_date'] read_only_fields = ('id', 'user_id', 'handle', 'upload_date',) def get_handle(self, instance): """ Return handle Args: instance: Returns: """ # get request from context request = self.context.get('request') # return download handle return get_blob_download_uri(instance, request) def get_upload_date(self, instance): """ Return upload date Args: instance: Returns: """ # Return instance generation time return str(instance.id.generation_time) def create(self, validated_data): """ Create and return a new `Blob` instance, given the validated data. Args: validated_data: Returns: """ # Create blob blob_object = Blob(filename=validated_data['blob'].name, user_id=str(validated_data['user'].id)) # Set file content blob_object.blob = validated_data['blob'].file # Save the blob return blob_api.insert(blob_object)
class UploadeBaseSerializer(serializers.Serializer): property_service = PropertyService() propertyId = IntegerField(min_value=1, required=True) modelName = CharField(min_length=2, required=True) image = ListField(child=FileField(), required=True) def create(self, validated_data): return self.property_service.upload_image(validated_data=validated_data)
class FileCreateSerializer(serializers.ModelSerializer): file = FileField(required=True) def create(self, validated_data): validated_data["name"] = validated_data.get("file")._name return super().create(validated_data) class Meta: model = Image fields = ("pk", "file")
class SAMLProviderImportSerializer(PassiveSerializer): """Import saml provider from XML Metadata""" name = CharField(required=True) # Using SlugField because https://github.com/OpenAPITools/openapi-generator/issues/3278 authorization_flow = SlugRelatedField( queryset=Flow.objects.filter(designation=FlowDesignation.AUTHORIZATION), slug_field="slug", ) file = FileField()
class SubmitResultCombinedSerializer(serializers.Serializer): # Result match = serializers.IntegerField() type = serializers.ChoiceField(choices=Result.TYPES) replay_file = serializers.FileField(required=False) game_steps = serializers.IntegerField() submitted_by = serializers.HiddenField( default=serializers.CurrentUserDefault()) arenaclient_log = FileField(required=False) # Bot bot1_data = FileField(required=False) bot2_data = FileField(required=False) # Participant bot1_log = FileField(required=False) bot2_log = FileField(required=False) bot1_avg_step_time = FloatField( required=False, validators=[validate_not_nan, validate_not_inf]) bot2_avg_step_time = FloatField( required=False, validators=[validate_not_nan, validate_not_inf])
class SocketSerializer(RevalidateMixin, MetadataMixin, DynamicFieldsMixin, HyperlinkedMixin, ModelSerializer): hyperlinks = ( ('self', 'socket-detail', ( 'instance.name', 'name', )), ('update', 'socket-update', ( 'instance.name', 'name', )), ('endpoints', 'socket-endpoint-endpoint', ( 'instance.name', 'name', )), ('handlers', 'socket-handler-list', ( 'instance.name', 'name', )), ('zip_file', 'socket-zip-file', ( 'instance.name', 'name', )), ) name = LowercaseCharField(validators=[ UniqueValidator(queryset=Socket.objects.all()), DjangoValidator() ]) zip_file = FileField(write_only=True) zip_file_list = JSONField(validators=[FileListValidator()], default=None, write_only=True) config = JSONField(validators=[validate_config], default={}) install_config = JSONField(write_only=True, default={}) status = DisplayedChoiceField(Socket.STATUSES.as_choices(), read_only=True) status_info = JSONField(read_only=True) installed = JSONField(read_only=True) files = serializers.SerializerMethodField() environment = SlugRelatedField(slug_field='name', queryset=SocketEnvironment.objects.all(), default=None, allow_null=True) class Meta: model = Socket fields = ('name', 'description', 'created_at', 'updated_at', 'version', 'status', 'status_info', 'install_url', 'metadata', 'config', 'zip_file', 'zip_file_list', 'installed', 'files', 'environment', 'install_config', ) read_only_fields = ('install_url', 'version') def get_files(self, obj): file_list = copy.deepcopy(obj.file_list) for val in file_list.values(): if not val['file'].startswith('<'): val['file'] = default_storage.url(val['file']) return file_list
def __init__(self, *args, **kwargs): super(CreateVerificationSerializer, self).__init__(*args, **kwargs) doc_types = DocumentType.objects.all() for doc_type in doc_types: self.fields[doc_type.api_key] = FileField( allow_null=True, max_length=100, required=False, validators=[validate_image_extension_api]) self.documents_data = { doc_type.api_key: None for doc_type in doc_types }
class ProgramSerializer(serializers.HyperlinkedModelSerializer): steps = ProgramStepSerializer(many=True, read_only=True) merchant = MerchantSerializer(read_only=True) program_logo = FileField(use_url=True) class Meta: model = Program fields = ('url', 'id', 'enroll_key', 'redeem_key', 'reward_key', 'publish_date', 'expiry_date', 'content', 'program_logo', 'steps', 'merchant') read_only_fields = ('enroll_key', 'redeem_key', 'reward_key', 'id', ) def to_representation(self, instance): ret = super().to_representation(instance) ret['content'] = html2text(ret['content'])[:-2] return ret
class EventSerializer(serializers.ModelSerializer): teacher_user = serializers.PrimaryKeyRelatedField( queryset=MyUser.objects.all()) student_user = serializers.PrimaryKeyRelatedField( many=True, queryset=MyUser.objects.all()) recurrence = serializers.PrimaryKeyRelatedField( allow_null=True, queryset=Recurrence.objects.all()) file = FileField(allow_null=True, required=False) class Meta: model = Event fields = [ 'id', 'title', 'start', 'end', 'teacher_user', 'student_user', 'isRecurrence', 'recurrence', 'comment', 'file', 'color' ]
class ProductSerializer(ModelSerializer): is_on_sale = BooleanField(read_only=True) current_price = FloatField(read_only=True) description = CharField(min_length=2, max_length=200) cart_items = OrderSerializer(many=True, read_only=True) # price = FloatField(min_value=1.00, max_value=100000) price = DecimalField( min_value=1.00, max_value=100000, max_digits=None, decimal_places=2, ) sale_start = DateTimeField( required=False, input_formats=['%I:%M %p %d %B %Y'], format=None, allow_null=True, help_text='Accepted format is "12:01 PM 16 April 2019"', style={'input_type': 'text', 'placeholder': '12:01 AM 28 July 2019'}, ) sale_end = DateTimeField( required=False, input_formats=['%I:%M %p %d %B %Y'], format=None, allow_null=True, help_text='Accepted format is "12:01 PM 16 April 2019"', style={'input_type': 'text', 'placeholder': '12:01 AM 28 July 2019'}, ) photo = ImageField(default=None) warranty = FileField(write_only=True, default=None) class Meta: model = Product fields = ( 'id', 'name', 'description', 'price', 'sale_start', 'sale_end', 'is_on_sale', 'current_price', 'cart_items', 'photo', 'warranty', ) def update(self, instance, validated_data): if validated_data.get('warranty', None): instance.description += '\n\nWarranty Information:\n' instance.description += b'; '.join( validated_data['warranty'].readlines() ).decode('utf-8') return super().update(instance, validated_data) def create(self, validated_data): validated_data.pop('warranty') # remove return Product.objects.create(**validated_data)
class RReadingCSVSerializer(ModelSerializer): file = FileField(label='Upload File') class Meta: model = RReading exclude = ['id', ] def create(self, validated_data): csv_input = validated_data.pop('file', None) id = validated_data.get("user") csv_file = csv_input if not csv_file.name.endswith('.csv'): messages.error(request, 'Please select a CSV file') data_set = csv_file.read().decode('UTF-8') io_string = io.StringIO(data_set) next(io_string) for column in csv.reader(io_string, delimiter=',', quotechar="|"): RReading.objects.create(user=id, intensity=column[0], level=column[1]) return validated_data
class SocketEnvironmentSerializer(RevalidateMixin, MetadataMixin, DynamicFieldsMixin, HyperlinkedMixin, ModelSerializer): hyperlinks = ( ('self', 'socket-environment-detail', ( 'instance.name', 'name', )), ) name = LowercaseCharField(validators=[ UniqueValidator(queryset=SocketEnvironment.objects.all()), DjangoValidator() ]) zip_file = FileField(write_only=True) status = DisplayedChoiceField(SocketEnvironment.STATUSES.as_choices(), read_only=True) status_info = JSONField(read_only=True) checksum = CharField(read_only=True) class Meta: model = SocketEnvironment fields = ('name', 'description', 'created_at', 'updated_at', 'status', 'status_info', 'metadata', 'zip_file', 'checksum')
class PictureUploadSerializer(serializers.HyperlinkedModelSerializer): file = FileField(allow_empty_file=False, required=True) class Meta: model = Picture fields = ("slug", "file", "name", "thumbnail", "id")
class FileUploadSerializer(PassiveSerializer): """Serializer to upload file""" file = FileField(required=False) clear = BooleanField(default=False)
EmailField(), { 'type': 'string', 'format': 'email' }, ), ( # JSONField JSONField(), { 'type': 'object' }, ), ( # FileField FileField(), { 'type': 'string', 'format': 'binary' }, ), ( # FloatField FloatField(), { 'type': 'number' }, ), ( # ImageField ImageField(),
class MerchantSerializer(serializers.HyperlinkedModelSerializer): brand_logo = FileField(use_url=True) class Meta: model = Merchant fields = ('url', 'name', 'email', 'address', 'phone', 'content', 'brand_logo')
class BlobSerializer(DocumentSerializer): """Blob serializer""" blob = FileField(write_only=True) handle = SerializerMethodField() upload_date = SerializerMethodField() if "core_linked_records_app" in settings.INSTALLED_APPS: pid = SerializerMethodField() class Meta(object): model = Blob fields = ["id", "user_id", "filename", "handle", "blob", "upload_date"] read_only_fields = ("id", "user_id", "filename", "handle", "upload_date") if "core_linked_records_app" in settings.INSTALLED_APPS: fields.append("pid") read_only_fields = read_only_fields + ("pid", ) def get_pid(self, instance): """Return pid Args: instance: Returns: """ # return pid if assigned if "core_linked_records_app" not in settings.INSTALLED_APPS: return None else: from core_linked_records_app.components.blob import ( api as linked_blob_api, ) from core_linked_records_app.settings import ID_PROVIDER_SYSTEM_NAME try: sub_url = reverse( "core_linked_records_provider_record", kwargs={ "provider": ID_PROVIDER_SYSTEM_NAME, "record": "" }, ) blob_pid = linked_blob_api.get_pid_for_blob(str(instance.id)) return urljoin(settings.SERVER_URI, join(sub_url, blob_pid.record_name)) except: return None def get_handle(self, instance): """Return handle Args: instance: Returns: """ # get request from context request = self.context.get("request") # return download handle return get_blob_download_uri(instance, request) def get_upload_date(self, instance): """Return upload date Args: instance: Returns: """ # Return instance generation time return str(instance.id.generation_time) def create(self, validated_data): """Create and return a new `Blob` instance, given the validated data. Args: validated_data: Returns: """ # Create blob blob_object = Blob( filename=validated_data["blob"].name, user_id=str(self.context["request"].user.id), ) # Set file content blob_object.blob = validated_data["blob"].file # Save the blob return blob_api.insert(blob_object, self.context["request"].user)
class DeploymentUploadSerializer(Serializer): deployment_file = FileField() class Meta: fields = ['deployment_file']
class ProgramStepSerializer(serializers.HyperlinkedModelSerializer): reward_logo = FileField(use_url=True) class Meta: model = ProgramStep fields = ('url', 'id', 'redeem', 'reward', 'reward_logo')
class FlowViewSet(ModelViewSet): """Flow Viewset""" queryset = Flow.objects.all() serializer_class = FlowSerializer lookup_field = "slug" search_fields = ["name", "slug", "designation", "title"] filterset_fields = ["flow_uuid", "name", "slug", "designation"] @permission_required(None, ["authentik_flows.view_flow_cache"]) @extend_schema(responses={200: CacheSerializer(many=False)}) @action(detail=False, pagination_class=None, filter_backends=[]) def cache_info(self, request: Request) -> Response: """Info about cached flows""" return Response(data={"count": len(cache.keys("flow_*"))}) @permission_required(None, ["authentik_flows.clear_flow_cache"]) @extend_schema( request=OpenApiTypes.NONE, responses={ 204: OpenApiResponse(description="Successfully cleared cache"), 400: OpenApiResponse(description="Bad request"), }, ) @action(detail=False, methods=["POST"]) def cache_clear(self, request: Request) -> Response: """Clear flow cache""" keys = cache.keys("flow_*") cache.delete_many(keys) LOGGER.debug("Cleared flow cache", keys=len(keys)) return Response(status=204) @permission_required( None, [ "authentik_flows.add_flow", "authentik_flows.change_flow", "authentik_flows.add_flowstagebinding", "authentik_flows.change_flowstagebinding", "authentik_flows.add_stage", "authentik_flows.change_stage", "authentik_policies.add_policy", "authentik_policies.change_policy", "authentik_policies.add_policybinding", "authentik_policies.change_policybinding", "authentik_stages_prompt.add_prompt", "authentik_stages_prompt.change_prompt", ], ) @extend_schema( request={ "multipart/form-data": inline_serializer("SetIcon", fields={"file": FileField()}) }, responses={ 204: OpenApiResponse(description="Successfully imported flow"), 400: OpenApiResponse(description="Bad request"), }, ) @action(detail=False, methods=["POST"], parser_classes=(MultiPartParser, )) def import_flow(self, request: Request) -> Response: """Import flow from .akflow file""" file = request.FILES.get("file", None) if not file: return HttpResponseBadRequest() importer = FlowImporter(file.read().decode()) valid = importer.validate() if not valid: return HttpResponseBadRequest() successful = importer.apply() if not successful: return Response(status=204) return HttpResponseBadRequest() @permission_required( "authentik_flows.export_flow", [ "authentik_flows.view_flow", "authentik_flows.view_flowstagebinding", "authentik_flows.view_stage", "authentik_policies.view_policy", "authentik_policies.view_policybinding", "authentik_stages_prompt.view_prompt", ], ) @extend_schema( responses={ "200": OpenApiResponse(response=OpenApiTypes.BINARY), }, ) @action(detail=True, pagination_class=None, filter_backends=[]) # pylint: disable=unused-argument def export(self, request: Request, slug: str) -> Response: """Export flow to .akflow file""" flow = self.get_object() exporter = FlowExporter(flow) response = JsonResponse(exporter.export(), encoder=DataclassEncoder, safe=False) response[ "Content-Disposition"] = f'attachment; filename="{flow.slug}.akflow"' return response @extend_schema(responses={200: FlowDiagramSerializer()}) @action(detail=True, pagination_class=None, filter_backends=[], methods=["get"]) # pylint: disable=unused-argument def diagram(self, request: Request, slug: str) -> Response: """Return diagram for flow with slug `slug`, in the format used by flowchart.js""" flow = self.get_object() header = [ DiagramElement("st", "start", "Start"), ] body: list[DiagramElement] = [] footer = [] # First, collect all elements we need for s_index, stage_binding in enumerate( get_objects_for_user( request.user, "authentik_flows.view_flowstagebinding").filter( target=flow).order_by("order")): for p_index, policy_binding in enumerate( get_objects_for_user( request.user, "authentik_policies.view_policybinding").filter( target=stage_binding).exclude( policy__isnull=True).order_by("order")): body.append( DiagramElement( f"stage_{s_index}_policy_{p_index}", "condition", f"Policy\n{policy_binding.policy.name}", )) body.append( DiagramElement( f"stage_{s_index}", "operation", f"Stage\n{stage_binding.stage.name}", )) # If the 2nd last element is a policy, we need to have an item to point to # for a negative case body.append(DiagramElement("e", "end", "End|future"), ) if len(body) == 1: footer.append("st(right)->e") else: # Actual diagram flow footer.append(f"st(right)->{body[0].identifier}") for index in range(len(body) - 1): element: DiagramElement = body[index] if element.type == "condition": # Policy passes, link policy yes to next stage footer.append( f"{element.identifier}(yes, right)->{body[index + 1].identifier}" ) # Policy doesn't pass, go to stage after next stage no_element = body[index + 1] if no_element.type != "end": no_element = body[index + 2] footer.append( f"{element.identifier}(no, bottom)->{no_element.identifier}" ) elif element.type == "operation": footer.append( f"{element.identifier}(bottom)->{body[index + 1].identifier}" ) diagram = "\n".join([str(x) for x in header + body + footer]) return Response({"diagram": diagram}) @permission_required("authentik_flows.change_flow") @extend_schema( request={ "multipart/form-data": inline_serializer("SetIcon", fields={"file": FileField()}) }, responses={ 200: OpenApiResponse(description="Success"), 400: OpenApiResponse(description="Bad request"), }, ) @action( detail=True, pagination_class=None, filter_backends=[], methods=["POST"], parser_classes=(MultiPartParser, ), ) # pylint: disable=unused-argument def set_background(self, request: Request, slug: str): """Set Flow background""" flow: Flow = self.get_object() icon = request.FILES.get("file", None) if not icon: return HttpResponseBadRequest() flow.background = icon flow.save() return Response({}) @permission_required("authentik_core.change_application") @extend_schema( request=inline_serializer("SetIconURL", fields={"url": CharField()}), responses={ 200: OpenApiResponse(description="Success"), 400: OpenApiResponse(description="Bad request"), }, ) @action( detail=True, pagination_class=None, filter_backends=[], methods=["POST"], ) # pylint: disable=unused-argument def set_background_url(self, request: Request, slug: str): """Set Flow background (as URL)""" flow: Flow = self.get_object() url = request.data.get("url", None) if not url: return HttpResponseBadRequest() flow.background = url flow.save() return Response({}) @extend_schema( responses={ 200: LinkSerializer(many=False), 400: OpenApiResponse(description="Flow not applicable"), }, ) @action(detail=True, pagination_class=None, filter_backends=[]) # pylint: disable=unused-argument def execute(self, request: Request, slug: str): """Execute flow for current user""" flow: Flow = self.get_object() planner = FlowPlanner(flow) planner.use_cache = False try: plan = planner.plan(self.request, {PLAN_CONTEXT_PENDING_USER: request.user}) self.request.session[SESSION_KEY_PLAN] = plan except FlowNonApplicableException as exc: return bad_request_message( request, _("Flow not applicable to current user/request: %(messages)s" % {"messages": str(exc)}), ) return Response({ "link": request._request.build_absolute_uri( reverse("authentik_core:if-flow", kwargs={"flow_slug": flow.slug})) })
class ApplicationViewSet(ModelViewSet): """Application Viewset""" queryset = Application.objects.all() serializer_class = ApplicationSerializer search_fields = [ "name", "slug", "meta_launch_url", "meta_description", "meta_publisher", ] lookup_field = "slug" ordering = ["name"] def _filter_queryset_for_list(self, queryset: QuerySet) -> QuerySet: """Custom filter_queryset method which ignores guardian, but still supports sorting""" for backend in list(self.filter_backends): if backend == ObjectPermissionsFilter: continue queryset = backend().filter_queryset(self.request, queryset, self) return queryset def _get_allowed_applications(self, queryset: QuerySet) -> list[Application]: applications = [] for application in queryset: engine = PolicyEngine(application, self.request.user, self.request) engine.build() if engine.passing: applications.append(application) return applications @extend_schema( request=inline_serializer( "CheckAccessRequest", fields={"for_user": IntegerField(required=False)}), responses={ 200: PolicyTestResultSerializer(), 404: OpenApiResponse(description="for_user user not found"), }, ) @action(detail=True, methods=["POST"]) # pylint: disable=unused-argument def check_access(self, request: Request, slug: str) -> Response: """Check access to a single application by slug""" # Don't use self.get_object as that checks for view_application permission # which the user might not have, even if they have access application = get_object_or_404(Application, slug=slug) # If the current user is superuser, they can set `for_user` for_user = self.request.user if self.request.user.is_superuser and "for_user" in request.data: for_user = get_object_or_404(User, pk=request.data.get("for_user")) engine = PolicyEngine(application, for_user, self.request) engine.build() result = engine.result response = PolicyTestResultSerializer(PolicyResult(False)) if result.passing: response = PolicyTestResultSerializer(PolicyResult(True)) if self.request.user.is_superuser: response = PolicyTestResultSerializer(result) return Response(response.data) @extend_schema(parameters=[ OpenApiParameter( name="superuser_full_list", location=OpenApiParameter.QUERY, type=OpenApiTypes.BOOL, ) ]) def list(self, request: Request) -> Response: """Custom list method that checks Policy based access instead of guardian""" self.request.session.pop(USER_LOGIN_AUTHENTICATED, None) queryset = self._filter_queryset_for_list(self.get_queryset()) self.paginate_queryset(queryset) should_cache = request.GET.get("search", "") == "" superuser_full_list = (str( request.GET.get("superuser_full_list", "false")).lower() == "true") if superuser_full_list and request.user.is_superuser: serializer = self.get_serializer(queryset, many=True) return self.get_paginated_response(serializer.data) allowed_applications = [] if not should_cache: allowed_applications = self._get_allowed_applications(queryset) if should_cache: LOGGER.debug("Caching allowed application list") allowed_applications = cache.get( user_app_cache_key(self.request.user.pk)) if not allowed_applications: allowed_applications = self._get_allowed_applications(queryset) cache.set( user_app_cache_key(self.request.user.pk), allowed_applications, timeout=86400, ) serializer = self.get_serializer(allowed_applications, many=True) return self.get_paginated_response(serializer.data) @permission_required("authentik_core.change_application") @extend_schema( request={ "multipart/form-data": inline_serializer("SetIcon", fields={"file": FileField()}) }, responses={ 200: OpenApiResponse(description="Success"), 400: OpenApiResponse(description="Bad request"), }, ) @action( detail=True, pagination_class=None, filter_backends=[], methods=["POST"], parser_classes=(MultiPartParser, ), ) # pylint: disable=unused-argument def set_icon(self, request: Request, slug: str): """Set application icon""" app: Application = self.get_object() icon = request.FILES.get("file", None) if not icon: return HttpResponseBadRequest() app.meta_icon = icon app.save() return Response({}) @permission_required("authentik_core.change_application") @extend_schema( request=inline_serializer("SetIconURL", fields={"url": CharField()}), responses={ 200: OpenApiResponse(description="Success"), 400: OpenApiResponse(description="Bad request"), }, ) @action( detail=True, pagination_class=None, filter_backends=[], methods=["POST"], ) # pylint: disable=unused-argument def set_icon_url(self, request: Request, slug: str): """Set application icon (as URL)""" app: Application = self.get_object() url = request.data.get("url", None) if not url: return HttpResponseBadRequest() app.meta_icon = url app.save() return Response({}) @permission_required("authentik_core.view_application", ["authentik_events.view_event"]) @extend_schema(responses={200: CoordinateSerializer(many=True)}) @action(detail=True, pagination_class=None, filter_backends=[]) # pylint: disable=unused-argument def metrics(self, request: Request, slug: str): """Metrics for application logins""" app = self.get_object() return Response( get_events_per_1h( action=EventAction.AUTHORIZE_APPLICATION, context__authorized_application__pk=app.pk.hex, ))
class FileUploaderSerializer(UploadeBaseSerializer): image = ListField(child=FileField(), required=True)