|
45 | 45 | from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream, user_is_person, is_individual_draft_author |
46 | 46 | from ietf.ietfauth.utils import role_required |
47 | 47 | from ietf.message.models import Message |
48 | | -from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName, DocUrlTagName |
| 48 | +from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName, DocUrlTagName, ExtResourceName |
49 | 49 | from ietf.person.fields import SearchableEmailField |
50 | 50 | from ietf.person.models import Person, Email |
51 | 51 | from ietf.utils.mail import send_mail, send_mail_message, on_behalf_of |
52 | 52 | from ietf.utils.textupload import get_cleaned_text_file_content |
| 53 | +from ietf.utils.validators import validate_external_resource_value |
53 | 54 | from ietf.utils import log |
54 | 55 | from ietf.mailtrigger.utils import gather_address_lists |
55 | 56 |
|
@@ -1255,6 +1256,88 @@ def format_urls(urls, fs="\n"): |
1255 | 1256 | title = "Additional document URLs" |
1256 | 1257 | return render(request, 'doc/edit_field.html',dict(doc=doc, form=form, title=title, info=info) ) |
1257 | 1258 |
|
| 1259 | + |
| 1260 | +def edit_doc_extresources(request, name): |
| 1261 | + class DocExtResourceForm(forms.Form): |
| 1262 | + resources = forms.CharField(widget=forms.Textarea, label="Additional Resources", required=False, |
| 1263 | + help_text=("Format: 'tag value (Optional description)'." |
| 1264 | + " Separate multiple entries with newline. When the value is a URL, use https:// where possible.") ) |
| 1265 | + |
| 1266 | + def clean_resources(self): |
| 1267 | + lines = [x.strip() for x in self.cleaned_data["resources"].splitlines() if x.strip()] |
| 1268 | + errors = [] |
| 1269 | + for l in lines: |
| 1270 | + parts = l.split() |
| 1271 | + if len(parts) == 1: |
| 1272 | + errors.append("Too few fields: Expected at least tag and value: '%s'" % l) |
| 1273 | + elif len(parts) >= 2: |
| 1274 | + name_slug = parts[0] |
| 1275 | + try: |
| 1276 | + name = ExtResourceName.objects.get(slug=name_slug) |
| 1277 | + except ObjectDoesNotExist: |
| 1278 | + errors.append("Bad tag in '%s': Expected one of %s" % (l, ', '.join([ o.slug for o in ExtResourceName.objects.all() ]))) |
| 1279 | + continue |
| 1280 | + value = parts[1] |
| 1281 | + try: |
| 1282 | + validate_external_resource_value(name, value) |
| 1283 | + except ValidationError as e: |
| 1284 | + e.message += " : " + value |
| 1285 | + errors.append(e) |
| 1286 | + if errors: |
| 1287 | + raise ValidationError(errors) |
| 1288 | + return lines |
| 1289 | + |
| 1290 | + def format_resources(resources, fs="\n"): |
| 1291 | + res = [] |
| 1292 | + for r in resources: |
| 1293 | + if r.display_name: |
| 1294 | + res.append("%s %s (%s)" % (r.name.slug, r.value, r.display_name.strip('()'))) |
| 1295 | + else: |
| 1296 | + res.append("%s %s" % (r.name.slug, r.value)) |
| 1297 | + # TODO: This is likely problematic if value has spaces. How then to delineate value and display_name? Perhaps in the short term move to comma or pipe separation. |
| 1298 | + # Might be better to shift to a formset instead of parsing these lines. |
| 1299 | + return fs.join(res) |
| 1300 | + |
| 1301 | + doc = get_object_or_404(Document, name=name) |
| 1302 | + |
| 1303 | + if not (has_role(request.user, ("Secretariat", "Area Director")) |
| 1304 | + or is_authorized_in_doc_stream(request.user, doc) |
| 1305 | + or is_individual_draft_author(request.user, doc)): |
| 1306 | + return HttpResponseForbidden("You do not have the necessary permissions to view this page") |
| 1307 | + |
| 1308 | + old_resources = format_resources(doc.docextresource_set.all()) |
| 1309 | + |
| 1310 | + if request.method == 'POST': |
| 1311 | + form = DocExtResourceForm(request.POST) |
| 1312 | + if form.is_valid(): |
| 1313 | + old_resources = sorted(old_resources.splitlines()) |
| 1314 | + new_resources = sorted(form.cleaned_data['resources']) |
| 1315 | + if old_resources != new_resources: |
| 1316 | + doc.docextresource_set.all().delete() |
| 1317 | + for u in new_resources: |
| 1318 | + parts = u.split(None, 2) |
| 1319 | + name = parts[0] |
| 1320 | + value = parts[1] |
| 1321 | + display_name = ' '.join(parts[2:]).strip('()') |
| 1322 | + doc.docextresource_set.create(value=value, name_id=name, display_name=display_name) |
| 1323 | + new_resources = format_resources(doc.docextresource_set.all()) |
| 1324 | + e = DocEvent(doc=doc, rev=doc.rev, by=request.user.person, type='changed_document') |
| 1325 | + e.desc = "Changed document external resources from:\n\n%s\n\nto:\n\n%s" % (old_resources, new_resources) |
| 1326 | + e.save() |
| 1327 | + doc.save_with_history([e]) |
| 1328 | + messages.success(request,"Document resources updated.") |
| 1329 | + else: |
| 1330 | + messages.info(request,"No change in Document resources.") |
| 1331 | + return redirect('ietf.doc.views_doc.document_main', name=doc.name) |
| 1332 | + else: |
| 1333 | + form = DocExtResourceForm(initial={'resources': old_resources, }) |
| 1334 | + |
| 1335 | + info = "Valid tags:<br><br> %s" % ', '.join([ o.slug for o in ExtResourceName.objects.all().order_by('slug') ]) |
| 1336 | + # May need to explain the tags more - probably more reason to move to a formset. |
| 1337 | + title = "Additional document resources" |
| 1338 | + return render(request, 'doc/edit_field.html',dict(doc=doc, form=form, title=title, info=info) ) |
| 1339 | + |
| 1340 | + |
1258 | 1341 | def request_publication(request, name): |
1259 | 1342 | """Request publication by RFC Editor for a document which hasn't |
1260 | 1343 | been through the IESG ballot process.""" |
|
0 commit comments