|
3 | 3 | import datetime |
4 | 4 |
|
5 | 5 | from django import forms |
| 6 | +from django.conf import settings |
| 7 | +from django.contrib import messages |
| 8 | +from django.contrib.auth.decorators import login_required |
| 9 | +from django.core.exceptions import ValidationError, ObjectDoesNotExist |
| 10 | +from django.core.validators import URLValidator |
6 | 11 | from django.db.models import Q |
7 | 12 | from django.http import HttpResponseRedirect, HttpResponseForbidden, Http404 |
8 | 13 | from django.shortcuts import render, get_object_or_404, redirect |
9 | 14 | from django.template.loader import render_to_string |
10 | | -from django.conf import settings |
11 | 15 | from django.forms.utils import ErrorList |
12 | | -from django.contrib.auth.decorators import login_required |
13 | 16 | from django.template.defaultfilters import pluralize |
14 | | -from django.contrib import messages |
15 | 17 |
|
16 | 18 | import debug # pyflakes:ignore |
17 | 19 |
|
|
33 | 35 | from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream, user_is_person |
34 | 36 | from ietf.ietfauth.utils import role_required |
35 | 37 | from ietf.message.models import Message |
36 | | -from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName |
| 38 | +from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName, DocUrlTagName |
37 | 39 | from ietf.person.fields import SearchableEmailField |
38 | 40 | from ietf.person.models import Person, Email |
39 | 41 | from ietf.utils.mail import send_mail, send_mail_message |
@@ -1110,14 +1112,89 @@ def edit_consensus(request, name): |
1110 | 1112 | }, |
1111 | 1113 | ) |
1112 | 1114 |
|
1113 | | -class PublicationForm(forms.Form): |
1114 | | - subject = forms.CharField(max_length=200, required=True) |
1115 | | - body = forms.CharField(widget=forms.Textarea, required=True, strip=False) |
| 1115 | +def edit_document_urls(request, name): |
| 1116 | + class DocumentUrlForm(forms.Form): |
| 1117 | + urls = forms.CharField(widget=forms.Textarea, label="Additional URLs", required=False, |
| 1118 | + help_text=("Format: 'tag https://site/path (Optional description)'." |
| 1119 | + " Separate multiple entries with newline. Prefer HTTPS URLs where possible.") ) |
| 1120 | + |
| 1121 | + def clean_urls(self): |
| 1122 | + lines = [x.strip() for x in self.cleaned_data["urls"].splitlines() if x.strip()] |
| 1123 | + url_validator = URLValidator() |
| 1124 | + for l in lines: |
| 1125 | + errors = [] |
| 1126 | + parts = l.split() |
| 1127 | + if len(parts) == 1: |
| 1128 | + errors.append("Too few fields: Expected at least url and tag: '%s'" % l) |
| 1129 | + elif len(parts) >= 2: |
| 1130 | + tag = parts[0] |
| 1131 | + url = parts[1] |
| 1132 | + try: |
| 1133 | + url_validator(url) |
| 1134 | + except ValidationError as e: |
| 1135 | + errors.append(e) |
| 1136 | + try: |
| 1137 | + DocUrlTagName.objects.get(slug=tag) |
| 1138 | + except ObjectDoesNotExist: |
| 1139 | + errors.append("Bad tag in '%s': Expected one of %s" % (l, ', '.join([ o.slug for o in DocUrlTagName.objects.all() ]))) |
| 1140 | + if errors: |
| 1141 | + raise ValidationError(errors) |
| 1142 | + return lines |
| 1143 | + |
| 1144 | + def format_urls(urls, fs="\n"): |
| 1145 | + res = [] |
| 1146 | + for u in urls: |
| 1147 | + if u.desc: |
| 1148 | + res.append(u"%s %s (%s)" % (u.tag.slug, u.url, u.desc.strip('()'))) |
| 1149 | + else: |
| 1150 | + res.append(u"%s %s" % (u.tag.slug, u.url)) |
| 1151 | + return fs.join(res) |
| 1152 | + |
| 1153 | + doc = get_object_or_404(Document, name=name) |
| 1154 | + |
| 1155 | + if not (has_role(request.user, ("Secretariat", "Area Director")) |
| 1156 | + or is_authorized_in_doc_stream(request.user, doc)): |
| 1157 | + return HttpResponseForbidden("You do not have the necessary permissions to view this page") |
| 1158 | + |
| 1159 | + old_urls = format_urls(doc.documenturl_set.all()) |
| 1160 | + |
| 1161 | + if request.method == 'POST': |
| 1162 | + form = DocumentUrlForm(request.POST) |
| 1163 | + if form.is_valid(): |
| 1164 | + old_urls = sorted(old_urls.splitlines()) |
| 1165 | + new_urls = sorted(form.cleaned_data['urls']) |
| 1166 | + if old_urls != new_urls: |
| 1167 | + doc.documenturl_set.all().delete() |
| 1168 | + for u in new_urls: |
| 1169 | + parts = u.split(None, 2) |
| 1170 | + tag = parts[0] |
| 1171 | + url = parts[1] |
| 1172 | + desc = ' '.join(parts[2:]).strip('()') |
| 1173 | + doc.documenturl_set.create(url=url, tag_id=tag, desc=desc) |
| 1174 | + new_urls = format_urls(doc.documenturl_set.all()) |
| 1175 | + e = DocEvent(doc=doc, rev=doc.rev, by=request.user.person, type='changed_document') |
| 1176 | + e.desc = "Changed document URLs from:\n\n%s\n\nto:\n\n%s" % (old_urls, new_urls) |
| 1177 | + e.save() |
| 1178 | + doc.save_with_history([e]) |
| 1179 | + messages.success(request,"Document URLs updated.") |
| 1180 | + else: |
| 1181 | + messages.info(request,"No change in Document URLs.") |
| 1182 | + return redirect('ietf.doc.views_doc.document_main', name=doc.name) |
| 1183 | + else: |
| 1184 | + form = DocumentUrlForm(initial={'urls': old_urls, }) |
| 1185 | + |
| 1186 | + info = "Valid tags:<br><br> %s" % ', '.join([ o.slug for o in DocUrlTagName.objects.all() ]) |
| 1187 | + title = "Additional document URLs" |
| 1188 | + return render(request, 'doc/edit_field.html',dict(doc=doc, form=form, title=title, info=info) ) |
1116 | 1189 |
|
1117 | 1190 | def request_publication(request, name): |
1118 | 1191 | """Request publication by RFC Editor for a document which hasn't |
1119 | 1192 | been through the IESG ballot process.""" |
1120 | 1193 |
|
| 1194 | + class PublicationForm(forms.Form): |
| 1195 | + subject = forms.CharField(max_length=200, required=True) |
| 1196 | + body = forms.CharField(widget=forms.Textarea, required=True, strip=False) |
| 1197 | + |
1121 | 1198 | doc = get_object_or_404(Document, type="draft", name=name, stream__in=("iab", "ise", "irtf")) |
1122 | 1199 |
|
1123 | 1200 | if not is_authorized_in_doc_stream(request.user, doc): |
|
0 commit comments