diff --git a/swh/web/add_forge_now/models.py b/swh/web/add_forge_now/models.py --- a/swh/web/add_forge_now/models.py +++ b/swh/web/add_forge_now/models.py @@ -4,6 +4,7 @@ # See top-level LICENSE file for more information import enum +from typing import List from django.db import models @@ -30,6 +31,40 @@ def choices(cls): return tuple((variant.name, variant.value) for variant in cls) + @classmethod + def allowed_next_statuses(cls, current_status: str) -> List[str]: + if current_status == cls.PENDING.name: + return [ + cls.WAITING_FOR_FEEDBACK.name, + cls.REJECTED.name, + cls.SUSPENDED.name, + ] + elif current_status == cls.WAITING_FOR_FEEDBACK.name: + return [cls.FEEDBACK_TO_HANDLE.name] + elif current_status == cls.FEEDBACK_TO_HANDLE.name: + return [ + cls.WAITING_FOR_FEEDBACK.name, + cls.ACCEPTED.name, + cls.REJECTED.name, + cls.SUSPENDED.name, + ] + elif current_status == cls.ACCEPTED.name: + return [cls.SCHEDULED.name] + elif current_status == cls.SCHEDULED.name: + return [cls.FIRST_LISTING_DONE.name] + elif current_status == cls.FIRST_LISTING_DONE.name: + return [cls.FIRST_ORIGIN_LOADED.name] + elif current_status == cls.FIRST_ORIGIN_LOADED.name: + return [] + elif current_status == cls.REJECTED.name: + return [] + elif current_status == cls.SUSPENDED.name: + return [cls.PENDING.name] + elif current_status == cls.DENIED.name: + return [] + else: + raise ValueError(f"Invalid request status: {current_status}") + class RequestActorRole(enum.Enum): MODERATOR = "moderator" diff --git a/swh/web/api/views/add_forge_now.py b/swh/web/api/views/add_forge_now.py --- a/swh/web/api/views/add_forge_now.py +++ b/swh/web/api/views/add_forge_now.py @@ -7,7 +7,9 @@ from typing import Union from django.core.exceptions import ObjectDoesNotExist -from django.forms import ModelForm +from django.db import transaction +from django.forms import CharField, ModelForm +from django.http import HttpResponseBadRequest from django.http.request import HttpRequest from django.http.response import HttpResponse, HttpResponseForbidden from rest_framework import serializers @@ -15,10 +17,14 @@ from rest_framework.response import Response from swh.web.add_forge_now.models import Request as AddForgeRequest +from swh.web.add_forge_now.models import RequestHistory as AddForgeNowRequestHistory +from swh.web.add_forge_now.models import RequestStatus as AddForgeNowRequestStatus from swh.web.api.apidoc import api_doc, format_docstring from swh.web.api.apiurls import api_route from swh.web.common.exc import BadInputExc +MODERATOR_ROLE = "swh.web.add_forge_now.moderator" + class AddForgeNowRequestForm(ModelForm): class Meta: @@ -32,12 +38,29 @@ ) +class AddForgeNowRequestHistoryForm(ModelForm): + new_status = CharField(max_length=200, required=False,) + + class Meta: + model = AddForgeNowRequestHistory + fields = ("text",) + + class AddForgeNowRequestSerializer(serializers.ModelSerializer): class Meta: model = AddForgeRequest fields = "__all__" +class AddForgeNowRequestPublicSerializer(serializers.ModelSerializer): + """Serializes AddForgeRequest without private fields. + """ + + class Meta: + model = AddForgeRequest + fields = ("forge_url", "forge_type", "status", "submission_date") + + @api_route( r"/add-forge/request/create", "api-1-add-forge-request-create", methods=["POST"], ) @@ -106,3 +129,83 @@ data = AddForgeNowRequestSerializer(add_forge_request).data return Response(data=data, status=201) + + +@api_route( + r"/add-forge/request/(?P[0-9]+)/update/", + "api-1-add-forge-request-update", + methods=["POST"], +) +@api_doc("/add-forge/request/update", tags=["hidden"]) +@format_docstring() +@transaction.atomic +def api_add_forge_request_update( + request: Union[HttpRequest, Request], id: int +) -> HttpResponse: + """ + .. http:post:: /api/1/add-forge/request/update/ + + Update a request to add a forge to the list of those crawled regularly + by Software Heritage. + + .. warning:: + That endpoint is not publicly available and requires authentication + in order to be able to request it. + + {common_headers} + + :