forked from ietf-tools/datatracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
322 lines (320 loc) · 15.7 KB
/
index.html
File metadata and controls
322 lines (320 loc) · 15.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
{# Copyright The IETF Trust 2007, All Rights Reserved #}
{% extends "base.html" %}
{% load static %}
{% block title %}API Notes{% endblock %}
{% block content %}
<h1>Datatracker API Notes</h1>
<div class="bio-text">
<h2 id="framework">Framework API</h2>
<p>
This section describes the autogenerated read-only API towards the database tables. See also
the
<a href="{% url 'ietf.submit.views.api_submission' %}">Internet-Draft submission API description</a>
and the
<a href="#iesg-position-api">IESG ballot position API description</a>
</p>
<p>
The datatracker API uses
<a href="https://django-tastypie.readthedocs.org/">tastypie</a>
to generate an API which mirrors the Django ORM (Object Relational Mapping)
for the database. Each Django model class maps down to the SQL database
tables and up to the API. The Django models classes are defined in the
models.py files of the datatracker. Browse the <a href="https://github.com/ietf-tools/datatracker">code tree</a>
for the models file in each app (such as <a href="https://github.com/ietf-tools/datatracker/blob/main/ietf/doc/models.py">ietf/doc/models.py</a>,
<a href="https://github.com/ietf-tools/datatracker/blob/main/ietf/group/models.py">ietf/group/models.py</a>, …).
</p>
<p>
The API top endpoint is at
<a href="{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}">{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}</a>.
The top
endpoint lists inferior endpoints, and thus permits some autodiscovery,
but there's really no substitute for looking at the actual ORM model classes.
Comparing a class in <code>models.py</code> with the equivalent endpoint may give
some clue (note that in the case of Group, it's a subclass of <code>GroupInfo</code>):
</p>
<ul>
<li>
<a href="{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/group/group/">{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/group/group/</a>
</li>
<li>
<a href="https://github.com/ietf-tools/datatracker/blob/main/ietf/group/models.py">
ietf/group/models.py
</a>
</li>
</ul>
<p>
Data is currently provided in JSON and XML format. Adding new formats is
fairly easy, if it should be found desirable.
</p>
<h3 id="framework-documents">Framework API: Documents</h3>
<p>
Documents are listed at
<a href="{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/doc/document/">{% url 'ietf.api.views.top_level' %}/doc/document/</a>.
</p>
<p>
In general, individual database objects are represented in the API with a path
composed of the model collection, the object name, and the object key. Most
objects have simple numerical keys, but documents have the document name as
key. Take <code>draft-ietf-eppext-keyrelay</code>. Documents have a model <code>Document</code> which
is described in the <code>doc</code> <code>models.py</code> file. Assembling the path components
<code>doc</code>, <code>document</code> (lowercase!) and <code>draft-ietf-eppext-keyrelay</code>, we get the
URL:
</p>
<p>
<a href="{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/doc/document/draft-ietf-eppext-keyrelay/">
{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/doc/document/draft-ietf-eppext-keyrelay/
</a>
</p>
<p>
If you instead do a search for this document, you will get a machine-readable
search result, which is composed of some meta-information about the search,
and a list with one element:
</p>
<p>
<a href="{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/doc/document/?name=draft-ietf-eppext-keyrelay">
api/v1/doc/document/?name=draft-ietf-eppext-keyrelay
</a>
</p>
<p>
To search for documents based on state, you need to know that documents have
multiple orthogonal states:
</p>
<ul>
<li>
If a document has an rfc-editor state, you can select for it by asking for, e.g.,
<a href="{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/doc/document/?limit=0&name__contains=-v6ops-&states__type__slug__in=draft-rfceditor">
v6ops documents which match <code>states__type__slug__in=draft-rfceditor</code>
</a>
</li>
<li>
If a document has an IESG state, you can select for it by asking for, e.g.,
<a href="{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/doc/document/?name__contains=-v6ops&states__type__slug__in=draft-iesg">
v6ops documents which match <code>states__type__slug__in=draft-iesg</code>
</a>
</li>
<li>
If a document has a WG state, you can select for it by asking for
documents which match <code>states__type__slug__in=draft-stream-ietf</code>
(but without additional filters, that's going to be a lot of documents)
</li>
<li>
States which match <code>states__type__slug__in=draft</code> describe the basic
Active/Expired/Dead whatever state of the Internet-Draft.
</li>
</ul>
<p>
You could use this in at least two alternative ways:
</p>
<ol>
<li>
You could either fetch and remember the different state groups of interest to you
with queries like
<pre>
$ curl '{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/doc/state/?format=json&limit=0&type__slug__in=draft-rfceditor'
$ curl '{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/doc/state/?format=json&limit=0&type__slug__in=draft-iesg'
$ curl '{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/doc/state/?format=json&limit=0&type__slug__in=draft-stream-ietf'
</pre>
and then match the listed "resource_uri" of the results to the states listed for each
document when you ask for
<pre>
$ curl '{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/doc/document/?limit=0&name__contains=-v6ops-'
</pre>
</li>
<li>
Or alternatively you could do a series of queries asking for matches to the RFC Editor
state first, then the IESG state, then the Stream state, and exclude earlier hits:
<pre>
$ curl '{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/doc/document/?limit=0&name__contains=-v6ops-&states__type__slug__in=draft-rfceditor' ...
$ curl '{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.views.top_level' %}/doc/document/?limit=0&name__contains=-v6ops-&states__type__slug__in=draft-iesg' ...
</pre>
etc.
</li>
</ol>
<h2 id="simplified-documents">Simplified Documents API</h2>
<p>
A simplified Documents API, intended for cases where only a limited set of
document attributes are necessary for an application is
available for all documents at the relative url <code>doc.json</code>, e.g.,
<code><a class="text-reset" href="{% url 'ietf.doc.views_doc.document_json' name='draft-ietf-poised95-std-proc-3' %}">{% url 'ietf.doc.views_doc.document_json' name='draft-ietf-poised95-std-proc-3' %}</a></code>.
You can also specify an RFC: <code><a class="text-reset" href="{% url 'ietf.doc.views_doc.document_json' name='rfc2026' %}">{% url 'ietf.doc.views_doc.document_json' name='rfc2026' %}</a></code>.
No API key is needed to access this.
</p>
<p>
The simplified document API takes no parameters, and is invoked with a HTTP GET.
</p>
<h2 id="iesg-position-api">IESG Ballot Position API</h2>
<p>
A simplified IESG ballot position interface, intended for automation, is
available at <code>{% url 'ietf.doc.views_ballot.api_set_position' %}</code>. Access is limited to area directors.
</p>
<p>
The interface requires the use of a personal API key, which can be created at
<a href="{% url 'ietf.ietfauth.views.apikey_index' %}">{% url 'ietf.ietfauth.views.apikey_index' %}</a>
</p>
<p>
The ballot position API takes the following parameters:
</p>
<ul>
<li>
<code>apikey</code> (required) which is the personal API key hash
</li>
<li>
<code>doc</code> (required) which is the balloted document name
</li>
<li>
<code>position</code> (required) which is the position slug, one of:
<code>yes</code>, <code>noobj</code>, <code>block</code>, <code>discuss</code>, <code>abstain</code>, <code>recuse</code>, <code>norecord</code>
.
</li>
<li>
<code>discuss</code> (required if position is <code>discuss</code>) which is the discuss text
</li>
<li>
<code>comment</code> (optional) which is comment text
</li>
</ul>
<p>
It returns an appropriate http result code, and a brief explanatory text message.
</p>
<p>
Here is an example:
</p>
<pre>
$ curl -S -F "apikey=AwAAABVR3D5GHkVMhspKSxBCVknGMmqikNIhT85kSnghjaV_pYy26WV92mm-jpdi" -F "doc=draft-ietf-lamps-eai-addresses" -F "position=noobj" -F "comment=Comment text" {{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.doc.views_ballot.api_set_position' %}
Done
</pre>
<h2 id="session-video-url-api">Set Session Video URL</h2>
<p>
This interface is intended for Meetecho, to provide a way to set the
URL of a video recording for a given session. It is available at
<code>{% url 'ietf.meeting.views.api_set_session_video_url' %}</code>.
Access is limited to recording managers.
</p>
<p>
The interface requires the use of a personal API key, which can be created at
<a href="{% url 'ietf.ietfauth.views.apikey_index' %}">{% url 'ietf.ietfauth.views.apikey_index' %}</a>
</p>
<p>
The ballot position API takes the following parameters:
</p>
<ul>
<li>
<code>apikey</code> (required) which is the personal API key hash
</li>
<li>
<code>meeting</code> (required) which is the meeting number
</li>
<li>
<code>group</code> (required) which is the group acronym
</li>
<li>
<code>item</code> (required) which is the chronological sequence number of the session (1 for a group's first session, 2 for the second, etc.)
</li>
<li>
<code>url</code> (required) which is the url that points to the video recording
</li>
</ul>
<p>
It returns an appropriate http result code, and a brief explanatory text message.
</p>
<p>
Here is an example:
</p>
<pre>
$ curl -S -F "apikey=DgAAAMLSi3coaE5TjrRs518xO8eBRlCmFF3eQcC8_SjUTtRGLGiJh7-1SYPT5WiS" -F "meeting=101" -F "group=mptcp" -F "item=1" -F "url=https://foo.example/beer/mptcp" {{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.meeting.views.api_set_session_video_url' %}
Done
</pre>
<h2 id="openid-connect">OpenID Connect</h2>
<p>
The datatracker supports
<a href="https://openid.net/connect/">OpenID Connect</a>,
but
not dynamic registration. The OpenID Connect Issuer is
<code>{{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.urls.oidc_issuer' %}</code>
</p>
<h2 id="datatracker-version">Datatracker Version</h2>
<p>
The datatracker version and release/patch date is available as a JSON blob at
<code>
<a href="{% url 'ietf.api.views.version' %}">
{% url 'ietf.api.views.version' %}
</a>
</code>.
</p>
<h2 id="personal-api-keys">
Personal API Keys
</h2>
<p>
The datatracker has some API endpoints that uses Personal API keys,
rather than having general access or requiring username/password
login, see for example details for
<code>{% url 'ietf.doc.views_ballot.api_set_position' %}</code>
<a href="#iesg-position-api">above</a>.
Personal API keys are available from your
<a href="{% url 'ietf.ietfauth.views.apikey_index' %}">
Account API Keys
</a>
page when you are logged in.
</p>
<p>
Personal API keys have some characteristics you should be aware of:
</p>
<ul>
<li>
Each API key is valid only for a specific endpoint. If you try to use a key for
a different API endpoint than it's created for, it will not work.
</li>
<li>
The API keys will cause you to be given access with the datatracker
roles you have, thus giving you appropriate access to the various
API endpoints according to the role limitations indicated for each
endpoint.
</li>
<li>
An API key will only give you access to its related endpoint if you have logged
in to the datatracker using your regular login and password during the last
{{ settings.UTILS_APIKEY_GUI_LOGIN_LIMIT_DAYS }} days. If you receive the
error message "<code>Too long since last regular login</code>" you should do
a regular login in order to activate access.
</li>
</ul>
<h2 id="signing-keys">
Signing Keys
</h2>
<p>
When sending notifications to other APIs, the datatracker may sign
information with a
<a href="{% url 'ietf.doc.views_doc.document_html' name='rfc7515' %}">
RFC
7515: JSON Web Signature (JWS)
</a>,
using a public/private keypair with
this public key:
</p>
<p>
<code>{{ key.export_public }}</code>
</p>
<p>
or alternatively:
</p>
<pre>{{ key.export_to_pem }}</pre>
<p>
To verify a signature and get the verified data using Python with the
<a href="https://jwcrypto.readthedocs.io/en/latest/">
jwcrypto
</a>
module,
you could do:
</p>
<pre>
from jwcrypto import jwk, jws
# ... receive json web signed data as 'data', used below ...
key = jwk.JWK()
key.import_from_pem(API_PUBLIC_KEY_PEM) # the key above
jwstoken = jws.JWS()
jwstoken.deserialize(data)
jwstoken.verify(key)
payload = jwstoken.payload
</pre>
</div>
{% endblock %}