Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions dev/deploy-to-container/settings_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,7 @@
SLIDE_STAGING_PATH = '/test/staging/'

DE_GFM_BINARY = '/usr/local/bin/de-gfm'

APP_API_TOKENS = {
"ietf.api.views_rpc" : ["devtoken"],
}
5 changes: 1 addition & 4 deletions docker/configs/settings_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,5 @@
STATIC_IETF_ORG_INTERNAL = "http://static"

APP_API_TOKENS = {
"ietf.api.views.rpc_person" : ["devtoken"],
"ietf.api.views.rpc_draft" : ["devtoken"],
"ietf.api.views.submitted_to_rpc" : ["devtoken"],
"ietf.api.views.create_demo_resources" : ["devtoken"], # remove for production!
"ietf.api.views_rpc" : ["devtoken"],
}
9 changes: 1 addition & 8 deletions ietf/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,7 @@
url(r'^rfcdiff-latest-json/(?P<name>[Rr][Ff][Cc] [0-9]+?)(\.txt|\.html)?/?$', api_views.rfcdiff_latest_json),
# direct authentication
url(r'^directauth/?$', api_views.directauth),
url(r'^rpc/person/(?P<person_id>[0-9]+)$', api_views.rpc_person),
url(r'^rpc/persons/$', api_views.rpc_persons),
url(r'^rpc/doc/submitted_to_rpc/$', api_views.submitted_to_rpc),
url(r'^rpc/doc/drafts/(?P<doc_id>[0-9]+)$', api_views.rpc_draft),
url(r'^rpc/person/create_demo_person/$', api_views.create_demo_person),
url(r'^rpc/doc/create_demo_draft/$', api_views.create_demo_draft),


url(r'^rpc/', include('ietf.api.urls_rpc')),
]

# Additional (standard) Tastypie endpoints
Expand Down
14 changes: 14 additions & 0 deletions ietf/api/urls_rpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright The IETF Trust 2023, All Rights Reserved

from ietf.api import views_rpc

from ietf.utils.urls import url

urlpatterns = [
url(r'^doc/create_demo_draft/$', views_rpc.create_demo_draft),
url(r'^doc/drafts/(?P<doc_id>[0-9]+)$', views_rpc.rpc_draft),
url(r'^doc/submitted_to_rpc/$', views_rpc.submitted_to_rpc),
url(r'^person/create_demo_person/$', views_rpc.create_demo_person),
url(r'^person/(?P<person_id>[0-9]+)$', views_rpc.rpc_person),
url(r'^persons/$', views_rpc.rpc_persons),
]
117 changes: 1 addition & 116 deletions ietf/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,9 @@
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.db.models import Q
from django.http import (
HttpResponse,
Http404,
JsonResponse,
HttpResponseNotAllowed,
HttpResponseNotFound,
)
from django.shortcuts import render, get_object_or_404
from django.urls import reverse
Expand All @@ -37,13 +33,10 @@
import debug # pyflakes:ignore

import ietf
from ietf.person.factories import PersonFactory # DO NOT MERGE INTO MAIN
from ietf.person.models import Person, Email
from ietf.api import _api_list
from ietf.api.serializer import JsonExportMixin
from ietf.api.ietf_utils import is_valid_token, requires_api_token
from ietf.doc.factories import WgDraftFactory # DO NOT MERGE INTO MAIN
from ietf.doc.models import Document
from ietf.api.ietf_utils import is_valid_token
from ietf.doc.utils import fuzzy_find_documents
from ietf.ietfauth.views import send_account_creation_email
from ietf.ietfauth.utils import role_required
Expand Down Expand Up @@ -446,112 +439,4 @@ def directauth(request):
else:
return HttpResponse(status=405)

@csrf_exempt
@requires_api_token
def rpc_person(request, person_id):
person = get_object_or_404(Person, pk=person_id)
return JsonResponse({
"id": person.id,
"plain_name": person.plain_name(),
})

@csrf_exempt
@requires_api_token("ietf.api.views.rpc_person")
def rpc_persons(request):
""" Get a batch of rpc person names"""
if request.method != "POST":
return HttpResponseNotAllowed(["POST"])

pks = json.loads(request.body)
response = dict()
for p in Person.objects.filter(pk__in=pks):
response[str(p.pk)] = p.plain_name()
return JsonResponse(response)

@csrf_exempt
@requires_api_token
def rpc_draft(request, doc_id):
if request.method != "GET":
return HttpResponseNotAllowed(["GET"])

try:
d = Document.objects.get(pk=doc_id, type_id="draft")
except Document.DoesNotExist:
return HttpResponseNotFound()
return JsonResponse({
"id": d.pk,
"name": d.name,
"rev": d.rev,
"stream": d.stream.slug,
"title": d.title,
"pages": d.pages,
"authors": [
{
"id": p.pk,
"plain_name": p.plain_name(),
} for p in d.documentauthor_set.all()
]
})

@csrf_exempt
@requires_api_token
def submitted_to_rpc(request):
""" Return documents in datatracker that have been submitted to the RPC but are not yet in the queue

Those queries overreturn - there may be things, particularly not from the IETF stream that are already in the queue.
"""
ietf_docs = Q(states__type_id="draft-iesg",states__slug__in=["ann"])
irtf_iab_ise_docs = Q(states__type_id__in=["draft-stream-iab","draft-stream-irtf","draft-stream-ise"],states__slug__in=["rfc-edit"])
#TODO: Need a way to talk about editorial stream docs
docs = Document.objects.filter(type_id="draft").filter(ietf_docs|irtf_iab_ise_docs)
response = {"submitted_to_rpc": []}
for doc in docs:
response["submitted_to_rpc"].append({"name":doc.name, "pk": doc.pk, "stream": doc.stream_id, "submitted": f"{doc.sent_to_rfc_editor_event().time:%Y-%m-%d}"}) #TODO reconcile timezone

return JsonResponse(response)


@csrf_exempt
@requires_api_token("ietf.api.views.create_demo_resources")
def create_demo_person(request):
""" Helper for creating rpc demo objects - SHOULD NOT MAKE IT INTO PRODUCTION

"""
if request.method != "POST":
return HttpResponseNotAllowed(["POST"])

request_params = json.loads(request.body)
name = request_params["name"]
person = Person.objects.filter(name=name).first() or PersonFactory(name=name)
return JsonResponse({"user_id":person.user.pk,"person_pk":person.pk})


@csrf_exempt
@requires_api_token("ietf.api.views.create_demo_resources")
def create_demo_draft(request):
""" Helper for creating rpc demo objects - SHOULD NOT MAKE IT INTO PRODUCTION

"""
if request.method != "POST":
return HttpResponseNotAllowed(["POST"])

request_params = json.loads(request.body)
name = request_params.get("name")
rev = request_params.get("rev")
states = request_params.get("states")
stream_id = request_params.get("stream_id", "ietf")
doc = None
if not name:
return HttpResponse(status=400, content="Name is required")
doc = Document.objects.filter(name=name).first()
if not doc:
kwargs = {"name": name, "stream_id": stream_id}
if states:
kwargs["states"] = states
if rev:
kwargs["rev"] = rev
doc = WgDraftFactory(**kwargs) # Yes, things may be a little strange if the stream isn't IETF, but until we nned something different...
event_type = "iesg_approved" if stream_id == "ietf" else "requested_publication"
if not doc.docevent_set.filter(type=event_type).exists(): # Not using get_or_create here on purpose - these are wobbly facades we're creating
doc.docevent_set.create(type=event_type, by_id=1, desc="Sent off to the RPC")
return JsonResponse({ "doc_id":doc.pk, "name":doc.name })
129 changes: 129 additions & 0 deletions ietf/api/views_rpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Copyright The IETF Trust 2023, All Rights Reserved

import json

from django.db.models import Q
from django.http import (
HttpResponse,
JsonResponse,
HttpResponseNotAllowed,
HttpResponseNotFound,
)
from django.shortcuts import get_object_or_404
from django.views.decorators.csrf import csrf_exempt

from ietf.api.ietf_utils import requires_api_token
from ietf.doc.factories import WgDraftFactory # DO NOT MERGE INTO MAIN
from ietf.doc.models import Document
from ietf.person.factories import PersonFactory # DO NOT MERGE INTO MAIN
from ietf.person.models import Person

@csrf_exempt
@requires_api_token
def rpc_person(request, person_id):
person = get_object_or_404(Person, pk=person_id)
return JsonResponse({
"id": person.id,
"plain_name": person.plain_name(),
})

@csrf_exempt
@requires_api_token("ietf.api.views_rpc")
def rpc_persons(request):
""" Get a batch of rpc person names"""
if request.method != "POST":
return HttpResponseNotAllowed(["POST"])

pks = json.loads(request.body)
response = dict()
for p in Person.objects.filter(pk__in=pks):
response[str(p.pk)] = p.plain_name()
return JsonResponse(response)

@csrf_exempt
@requires_api_token("ietf.api.views_rpc")
def rpc_draft(request, doc_id):
if request.method != "GET":
return HttpResponseNotAllowed(["GET"])

try:
d = Document.objects.get(pk=doc_id, type_id="draft")
except Document.DoesNotExist:
return HttpResponseNotFound()
return JsonResponse({
"id": d.pk,
"name": d.name,
"rev": d.rev,
"stream": d.stream.slug,
"title": d.title,
"pages": d.pages,
"authors": [
{
"id": p.pk,
"plain_name": p.plain_name(),
} for p in d.documentauthor_set.all()
]
})

@csrf_exempt
@requires_api_token("ietf.api.views_rpc")
def submitted_to_rpc(request):
""" Return documents in datatracker that have been submitted to the RPC but are not yet in the queue

Those queries overreturn - there may be things, particularly not from the IETF stream that are already in the queue.
"""
ietf_docs = Q(states__type_id="draft-iesg",states__slug__in=["ann"])
irtf_iab_ise_docs = Q(states__type_id__in=["draft-stream-iab","draft-stream-irtf","draft-stream-ise"],states__slug__in=["rfc-edit"])
#TODO: Need a way to talk about editorial stream docs
docs = Document.objects.filter(type_id="draft").filter(ietf_docs|irtf_iab_ise_docs)
response = {"submitted_to_rpc": []}
for doc in docs:
response["submitted_to_rpc"].append({"name":doc.name, "pk": doc.pk, "stream": doc.stream_id, "submitted": f"{doc.sent_to_rfc_editor_event().time:%Y-%m-%d}"}) #TODO reconcile timezone

return JsonResponse(response)


@csrf_exempt
@requires_api_token("ietf.api.views_rpc")
def create_demo_person(request):
""" Helper for creating rpc demo objects - SHOULD NOT MAKE IT INTO PRODUCTION

"""
if request.method != "POST":
return HttpResponseNotAllowed(["POST"])

request_params = json.loads(request.body)
name = request_params["name"]
person = Person.objects.filter(name=name).first() or PersonFactory(name=name)
return JsonResponse({"user_id":person.user.pk,"person_pk":person.pk})


@csrf_exempt
@requires_api_token("ietf.api.views_rpc")
def create_demo_draft(request):
""" Helper for creating rpc demo objects - SHOULD NOT MAKE IT INTO PRODUCTION

"""
if request.method != "POST":
return HttpResponseNotAllowed(["POST"])

request_params = json.loads(request.body)
name = request_params.get("name")
rev = request_params.get("rev")
states = request_params.get("states")
stream_id = request_params.get("stream_id", "ietf")
doc = None
if not name:
return HttpResponse(status=400, content="Name is required")
doc = Document.objects.filter(name=name).first()
if not doc:
kwargs = {"name": name, "stream_id": stream_id}
if states:
kwargs["states"] = states
if rev:
kwargs["rev"] = rev
doc = WgDraftFactory(**kwargs) # Yes, things may be a little strange if the stream isn't IETF, but until we nned something different...
event_type = "iesg_approved" if stream_id == "ietf" else "requested_publication"
if not doc.docevent_set.filter(type=event_type).exists(): # Not using get_or_create here on purpose - these are wobbly facades we're creating
doc.docevent_set.create(type=event_type, by_id=1, desc="Sent off to the RPC")
return JsonResponse({ "doc_id":doc.pk, "name":doc.name })
2 changes: 1 addition & 1 deletion rpcapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ info:
description: Datatracker RPC API
version: 1.0.0
servers:
- url: 'http://localhost:8000/api/rpc/'
- url: 'http://localhost:8000/api/rpc'
paths:
/person/{personId}:
get:
Expand Down