|
13 | 13 | from django.conf import settings |
14 | 14 | from django.contrib import messages |
15 | 15 | from django.contrib.auth.decorators import login_required |
16 | | -from django.core.exceptions import ValidationError, ObjectDoesNotExist |
17 | 16 | from django.db.models import Q |
18 | 17 | from django.http import HttpResponseRedirect, Http404 |
19 | 18 | from django.shortcuts import render, get_object_or_404, redirect |
|
35 | 34 | from ietf.doc.utils import ( add_state_change_event, can_adopt_draft, can_unadopt_draft, |
36 | 35 | get_tags_for_stream_id, nice_consensus, update_action_holders, |
37 | 36 | update_reminder, update_telechat, make_notify_changed_event, get_initial_notify, |
38 | | - set_replaces_for_document, default_consensus, tags_suffix, ) |
| 37 | + set_replaces_for_document, default_consensus, tags_suffix, can_edit_docextresources, |
| 38 | + update_doc_extresources ) |
39 | 39 | from ietf.doc.lastcall import request_last_call |
40 | 40 | from ietf.doc.fields import SearchableDocAliasesField |
| 41 | +from ietf.doc.forms import ExtResourceForm |
41 | 42 | from ietf.group.models import Group, Role, GroupFeatures |
42 | 43 | from ietf.iesg.models import TelechatDate |
43 | | -from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream, user_is_person, is_individual_draft_author |
| 44 | +from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream, user_is_person |
44 | 45 | from ietf.ietfauth.utils import role_required |
45 | 46 | from ietf.mailtrigger.utils import gather_address_lists |
46 | 47 | from ietf.message.models import Message |
47 | | -from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName, ExtResourceName |
| 48 | +from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName |
48 | 49 | from ietf.person.fields import SearchableEmailField |
49 | 50 | from ietf.person.models import Person, Email |
50 | 51 | from ietf.utils.mail import send_mail, send_mail_message, on_behalf_of |
51 | 52 | from ietf.utils.textupload import get_cleaned_text_file_content |
52 | | -from ietf.utils.validators import validate_external_resource_value |
53 | 53 | from ietf.utils import log |
54 | 54 | from ietf.utils.response import permission_denied |
55 | 55 |
|
@@ -1205,81 +1205,23 @@ def edit_consensus(request, name): |
1205 | 1205 |
|
1206 | 1206 |
|
1207 | 1207 | def edit_doc_extresources(request, name): |
1208 | | - class DocExtResourceForm(forms.Form): |
1209 | | - resources = forms.CharField(widget=forms.Textarea, label="Additional Resources", required=False, |
1210 | | - help_text=("Format: 'tag value (Optional description)'." |
1211 | | - " Separate multiple entries with newline. When the value is a URL, use https:// where possible.") ) |
1212 | | - |
1213 | | - def clean_resources(self): |
1214 | | - lines = [x.strip() for x in self.cleaned_data["resources"].splitlines() if x.strip()] |
1215 | | - errors = [] |
1216 | | - for l in lines: |
1217 | | - parts = l.split() |
1218 | | - if len(parts) == 1: |
1219 | | - errors.append("Too few fields: Expected at least tag and value: '%s'" % l) |
1220 | | - elif len(parts) >= 2: |
1221 | | - name_slug = parts[0] |
1222 | | - try: |
1223 | | - name = ExtResourceName.objects.get(slug=name_slug) |
1224 | | - except ObjectDoesNotExist: |
1225 | | - errors.append("Bad tag in '%s': Expected one of %s" % (l, ', '.join([ o.slug for o in ExtResourceName.objects.all() ]))) |
1226 | | - continue |
1227 | | - value = parts[1] |
1228 | | - try: |
1229 | | - validate_external_resource_value(name, value) |
1230 | | - except ValidationError as e: |
1231 | | - e.message += " : " + value |
1232 | | - errors.append(e) |
1233 | | - if errors: |
1234 | | - raise ValidationError(errors) |
1235 | | - return lines |
1236 | | - |
1237 | | - def format_resources(resources, fs="\n"): |
1238 | | - res = [] |
1239 | | - for r in resources: |
1240 | | - if r.display_name: |
1241 | | - res.append("%s %s (%s)" % (r.name.slug, r.value, r.display_name.strip('()'))) |
1242 | | - else: |
1243 | | - res.append("%s %s" % (r.name.slug, r.value)) |
1244 | | - # 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. |
1245 | | - # Might be better to shift to a formset instead of parsing these lines. |
1246 | | - return fs.join(res) |
1247 | | - |
1248 | 1208 | doc = get_object_or_404(Document, name=name) |
1249 | 1209 |
|
1250 | | - if not (has_role(request.user, ("Secretariat", "Area Director")) |
1251 | | - or is_authorized_in_doc_stream(request.user, doc) |
1252 | | - or is_individual_draft_author(request.user, doc)): |
| 1210 | + if not can_edit_docextresources(request.user, doc): |
1253 | 1211 | permission_denied(request, "You do not have the necessary permissions to view this page.") |
1254 | 1212 |
|
1255 | | - old_resources = format_resources(doc.docextresource_set.all()) |
1256 | | - |
1257 | 1213 | if request.method == 'POST': |
1258 | | - form = DocExtResourceForm(request.POST) |
| 1214 | + form = ExtResourceForm(request.POST) |
1259 | 1215 | if form.is_valid(): |
1260 | | - old_resources = sorted(old_resources.splitlines()) |
1261 | | - new_resources = sorted(form.cleaned_data['resources']) |
1262 | | - if old_resources != new_resources: |
1263 | | - doc.docextresource_set.all().delete() |
1264 | | - for u in new_resources: |
1265 | | - parts = u.split(None, 2) |
1266 | | - name = parts[0] |
1267 | | - value = parts[1] |
1268 | | - display_name = ' '.join(parts[2:]).strip('()') |
1269 | | - doc.docextresource_set.create(value=value, name_id=name, display_name=display_name) |
1270 | | - new_resources = format_resources(doc.docextresource_set.all()) |
1271 | | - e = DocEvent(doc=doc, rev=doc.rev, by=request.user.person, type='changed_document') |
1272 | | - e.desc = "Changed document external resources from:\n\n%s\n\nto:\n\n%s" % (old_resources, new_resources) |
1273 | | - e.save() |
1274 | | - doc.save_with_history([e]) |
| 1216 | + if update_doc_extresources(doc, form.cleaned_data['resources'], by=request.user.person): |
1275 | 1217 | messages.success(request,"Document resources updated.") |
1276 | 1218 | else: |
1277 | 1219 | messages.info(request,"No change in Document resources.") |
1278 | 1220 | return redirect('ietf.doc.views_doc.document_main', name=doc.name) |
1279 | 1221 | else: |
1280 | | - form = DocExtResourceForm(initial={'resources': old_resources, }) |
| 1222 | + form = ExtResourceForm(initial={'resources': doc.docextresource_set.all()}) |
1281 | 1223 |
|
1282 | | - info = "Valid tags:<br><br> %s" % ', '.join([ o.slug for o in ExtResourceName.objects.all().order_by('slug') ]) |
| 1224 | + info = "Valid tags:<br><br> %s" % ', '.join(form.valid_resource_tags()) |
1283 | 1225 | # May need to explain the tags more - probably more reason to move to a formset. |
1284 | 1226 | title = "Additional document resources" |
1285 | 1227 | return render(request, 'doc/edit_field.html',dict(doc=doc, form=form, title=title, info=info) ) |
|
0 commit comments