Repository: ietf-tools/datatracker

Issue:
Provide more detail in api submission response when submissions are closed.
### (Modified from the original report below)
The api response when submissions are closed could be more informative. Say the same things we say on the Web UI.

e.g.
```
 Warning: Currently in I-D submission blackout period.
The last submission time for the I-D submission was 2023-03-13 23:59 UTC.
The I-D submission tool will be reopened after 2023-03-25 23:59 JST (IETF-meeting local time).
```


### Original Report: 
#### Describe the issue

Using Martin Thompson github repository template, which I have used successfully before, I tried to submit an updated draft and got the following error.

```
{"error": "Validation Error", "messages": ["The submission tool is currently shut down"]}
```

Is the submission tool not working and do I just resubmit later or is this error message missapplied and something else is wrong?



Here is the full log.


```
+ lib/trace.sh versioned/draft-ssmith-acdc-03.xml -s upload-request curl -sS -D versioned/.draft-ssmith-acdc-03.upload -F user=sam@prosapien.com -F xml=@versioned/draft-ssmith-acdc-03.xml https://datatracker.ietf.org/api/submission
[53](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:54)
+ echo
[54](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:55)
{"error": "Validation Error", "messages": ["The submission tool is currently shut down"]}
[55](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:56)
+ grep -q '^HTTP/\S\S* 200\b'
[56](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:57)
+ head -1 versioned/.draft-ssmith-acdc-03.upload
[57](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:58)
+ lib/trace.sh versioned/draft-ssmith-acdc-03.xml -s upload-result '!' cat versioned/.draft-ssmith-acdc-03.upload
[58](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:59)
HTTP/2 400 
[59](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:60)
date: Wed, 15 Mar 2023 17:26:33 GMT
[60](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:61)
content-type: application/json
[61](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:62)
content-length: 89
[62](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:63)
strict-transport-security: max-age=3600; includeSubDomains
[63](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:64)
x-content-type-options: nosniff
[64](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:65)
x-xss-protection: 1; mode=block
[65](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:66)
x-frame-options: SAMEORIGIN
[66](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:67)
referrer-policy: strict-origin-when-cross-origin
[67](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:68)
vary: Cookie, Origin
[68](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:69)
cf-cache-status: DYNAMIC
[69](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:70)
server: cloudflare
[70](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:71)
cf-ray: 7a8676480ee8587e-IAD
[71](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:72)
alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400
[72](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:73)

[73](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:74)
make[1]: *** [lib/upload.mk:27: versioned/.draft-ssmith-acdc-03.upload] Error 1
[74](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:75)
make[1]: *** Deleting file 'versioned/.draft-ssmith-acdc-03.upload'
[75](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:76)
rm versioned/draft-ssmith-acdc-03.md
[76](https://github.com/WebOfTrust/ietf-acdc/actions/runs/4429158182/jobs/7769234531#step:8:77)
make: *** [lib/upload.mk:22: upload] Error 2
```

### Code of Conduct

- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)


Discussion:
The draft submission deadline for 116 was last Monday.
See https://datatracker.ietf.org/meeting/important-dates

The embargo will open when the meeting starts.

If you have a draft that shouldn't be embargoed, contact your area director or stream manager to arrange a manual post.
See also https://authors.ietf.org/en/submitting-your-internet-draft#submission-deadlines
We might want to improve the error message (I.e., add more information to it).
Make a concrete suggestion?
Use the same message shown on the web? I.e. mention the period of time it's down for and why.

Resolving patch:
diff --git a/ietf/submit/forms.py b/ietf/submit/forms.py
--- a/ietf/submit/forms.py
+++ b/ietf/submit/forms.py
@@ -194,7 +194,7 @@ def cleanup():  # called when context exited, even in case of exception
 
     def clean(self):
         if self.shutdown and not has_role(self.request.user, "Secretariat"):
-            raise forms.ValidationError('The submission tool is currently shut down')
+            raise forms.ValidationError(self.cutoff_warning)
 
         # check general submission rate thresholds before doing any more work
         today = date_today()
@@ -383,7 +383,7 @@ def format_messages(where, e, log):
             return msgs
 
         if self.shutdown and not has_role(self.request.user, "Secretariat"):
-            raise forms.ValidationError('The submission tool is currently shut down')
+            raise forms.ValidationError(self.cutoff_warning)
 
         for ext in self.formats:
             f = self.cleaned_data.get(ext, None)


Test patch:
diff --git a/ietf/submit/tests.py b/ietf/submit/tests.py
--- a/ietf/submit/tests.py
+++ b/ietf/submit/tests.py
@@ -2744,6 +2744,10 @@ def supply_extra_metadata(self, name, status_url, submitter_name, submitter_emai
 class ApiSubmissionTests(BaseSubmitTestCase):
     TASK_TO_MOCK = "ietf.submit.views.process_and_accept_uploaded_submission_task"
 
+    def setUp(self):
+        super().setUp()
+        MeetingFactory(type_id='ietf', date=date_today()+datetime.timedelta(days=60))
+
     def test_upload_draft(self):
         """api_submission accepts a submission and queues it for processing"""
         url = urlreverse('ietf.submit.views.api_submission')
@@ -2890,6 +2894,24 @@ def test_submission_status(self):
         r = self.client.get(urlreverse('ietf.submit.views.api_submission_status', kwargs={'submission_id': '999999'}))
         self.assertEqual(r.status_code, 404)
 
+    def test_upload_blackout(self):
+        """api_submission returns a useful error in the blackout period"""
+        # Put today in the blackout period
+        meeting = Meeting.get_current_meeting()
+        meeting.importantdate_set.create(name_id='idcutoff',date=date_today()-datetime.timedelta(days=2))
+
+        url = urlreverse('ietf.submit.views.api_submission')
+        xml, author = submission_file('draft-somebody-test-00', 'draft-somebody-test-00.xml', None, 'test_submission.xml')
+        data = {
+            'xml': xml,
+            'user': author.user.username,
+        }
+
+        with mock.patch('ietf.submit.views.process_uploaded_submission_task'):
+            r = self.client.post(url, data)
+        self.assertContains(r, 'The last submission time for the I-D submission was', status_code=400)
+
+ 
 
 class SubmissionUploadFormTests(BaseSubmitTestCase):
     def test_check_submission_thresholds(self):