added ways to see and edit PersonExtResources.

- Legacy-Id: 17869
This commit is contained in:
Robert Sparks 2020-05-21 20:10:04 +00:00
parent 38ba0f401d
commit b7f45dba05
6 changed files with 180 additions and 2 deletions

View file

@ -647,4 +647,44 @@ class IetfAuthTests(TestCase):
self.assertIn("API key usage", mail['subject'])
self.assertIn(" %s times" % count, body)
self.assertIn(date, body)
def test_edit_person_extresources(self):
url = urlreverse('ietf.ietfauth.views.edit_person_externalresources')
person = PersonFactory()
r = self.client.get(url)
self.assertNotEqual(r.status_code, 200)
self.client.login(username=person.user.username,password=person.user.username+'+password')
r = self.client.get(url)
self.assertEqual(r.status_code,200)
q = PyQuery(r.content)
self.assertEqual(len(q('form textarea[id=id_resources]')),1)
badlines = (
'github_repo https://github3.com/some/repo',
'github_notify badaddr',
'website /not/a/good/url'
'notavalidtag blahblahblah'
)
for line in badlines:
r = self.client.post(url, dict(resources=line, submit="1"))
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(q('.alert-danger'))
goodlines = """
github_repo https://github.com/some/repo Some display text
github_notify notify@example.com
github_username githubuser
website http://example.com/http/is/fine
"""
r = self.client.post(url, dict(resources=goodlines, submit="1"))
self.assertEqual(r.status_code,302)
self.assertEqual(person.personextresource_set.count(), 4)
self.assertEqual(person.personextresource_set.get(name__slug='github_repo').display_name, 'Some display text')

View file

@ -18,6 +18,7 @@ urlpatterns = [
url(r'^logout/$', logout),
url(r'^password/$', views.change_password),
url(r'^profile/$', views.profile),
url(r'^editexternalresources/$', views.edit_person_externalresources),
url(r'^reset/$', views.password_reset),
url(r'^reset/confirm/(?P<auth>[^/]+)/$', views.confirm_password_reset),
url(r'^review/$', views.review_overview),

View file

@ -67,12 +67,15 @@ from ietf.ietfauth.forms import ( RegistrationForm, PasswordForm, ResetPasswordF
from ietf.ietfauth.htpasswd import update_htpasswd_file
from ietf.ietfauth.utils import role_required, has_role
from ietf.mailinglists.models import Subscribed, Whitelisted
from ietf.name.models import ExtResourceName
from ietf.person.models import Person, Email, Alias, PersonalApiKey, PERSON_API_KEY_VALUES
from ietf.review.models import ReviewerSettings, ReviewWish, ReviewAssignment
from ietf.review.utils import unavailable_periods_to_list, get_default_filter_re
from ietf.doc.fields import SearchableDocumentField
from ietf.utils.decorators import person_required
from ietf.utils.mail import send_mail
from ietf.utils.validators import validate_external_resource_value
def index(request):
return render(request, 'registration/index.html')
@ -286,6 +289,79 @@ def profile(request):
'settings':settings,
})
@login_required
@person_required
def edit_person_externalresources(request):
class PersonExtResourceForm(forms.Form):
resources = forms.CharField(widget=forms.Textarea, label="Additional Resources", required=False,
help_text=("Format: 'tag value (Optional description)'."
" Separate multiple entries with newline. When the value is a URL, use https:// where possible.") )
def clean_resources(self):
lines = [x.strip() for x in self.cleaned_data["resources"].splitlines() if x.strip()]
errors = []
for l in lines:
parts = l.split()
if len(parts) == 1:
errors.append("Too few fields: Expected at least tag and value: '%s'" % l)
elif len(parts) >= 2:
name_slug = parts[0]
try:
name = ExtResourceName.objects.get(slug=name_slug)
except ObjectDoesNotExist:
errors.append("Bad tag in '%s': Expected one of %s" % (l, ', '.join([ o.slug for o in ExtResourceName.objects.all() ])))
continue
value = parts[1]
try:
validate_external_resource_value(name, value)
except ValidationError as e:
e.message += " : " + value
errors.append(e)
if errors:
raise ValidationError(errors)
return lines
def format_resources(resources, fs="\n"):
res = []
for r in resources:
if r.display_name:
res.append("%s %s (%s)" % (r.name.slug, r.value, r.display_name.strip('()')))
else:
res.append("%s %s" % (r.name.slug, r.value))
# 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.
# Might be better to shift to a formset instead of parsing these lines.
return fs.join(res)
person = request.user.person
old_resources = format_resources(person.personextresource_set.all())
if request.method == 'POST':
form = PersonExtResourceForm(request.POST)
if form.is_valid():
old_resources = sorted(old_resources.splitlines())
new_resources = sorted(form.cleaned_data['resources'])
if old_resources != new_resources:
person.personextresource_set.all().delete()
for u in new_resources:
parts = u.split(None, 2)
name = parts[0]
value = parts[1]
display_name = ' '.join(parts[2:]).strip('()')
person.personextresource_set.create(value=value, name_id=name, display_name=display_name)
new_resources = format_resources(person.personextresource_set.all())
messages.success(request,"Person resources updated.")
else:
messages.info(request,"No change in Person resources.")
return redirect('ietf.ietfauth.views.profile')
else:
form = PersonExtResourceForm(initial={'resources': old_resources, })
info = "Valid tags:<br><br> %s" % ', '.join([ o.slug for o in ExtResourceName.objects.all().order_by('slug') ])
# May need to explain the tags more - probably more reason to move to a formset.
title = "Additional person resources"
return render(request, 'ietfauth/edit_field.html',dict(person=person, form=form, title=title, info=info) )
def confirm_new_email(request, auth):
try:
username, email = django.core.signing.loads(auth, salt="add_email", max_age=settings.DAYS_TO_EXPIRE_REGISTRATION_LINK * 24 * 60 * 60)

View file

@ -0,0 +1,33 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load bootstrap3 %}
{% block title %}
{{ title }} {{ person.plain_name }}
{% endblock %}
{% block content %}
{% origin %}
<h1>{{ title }}<br><small>{{ person.plain_name }}</small></h1>
<p>
<b>
{{ info|safe }}
</b>
</p>
<form enctype="multipart/form-data" method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<!-- Regarding placement of buttons: https://www.lukew.com/ff/entry.asp?571 -->
<button type="submit" class="btn btn-primary" name="submit" value="Save">Submit</button>
<a class="btn btn-default pull-right" href="{% url "ietf.ietfauth.views.profile" %}">Back</a>
{% endbuttons %}
</form>
{% endblock %}

View file

@ -57,7 +57,19 @@
</div>
{% endif %}
{% if person.personextresource_set.exists %}
<div class="col-md-12">
<h2 id="extresources">External Resources</h2>
<table class="table">
{% for extres in person.personextresource_set.all %}
<tr>
<td class="col-md-1"><span title="{{ extres.name.name }}">{% firstof extres.display_name extres.name.name %}</span></td>
<td class="col-md-11">{{extres.value}}</td>
</tr>
{% endfor %}
</table>
</div>
{% endif %}
<div class="col-md-6">
<h2 id="rfcs">RFCs</h2>

View file

@ -94,7 +94,7 @@
<label class="col-sm-2 control-label">Nomcom Eligible</label>
<div class="col-sm-1 form-control-static">{{person|is_nomcom_eligible|yesno:'Yes,No,No'}}</div>
<div class="col-sm-9">
<p class="alert alert-info form-control-static ">
<p class="alert alert-info form-control-static">
This calculation is EXPERIMENTAL.<br/>
If you believe it is incorrect, make sure you've added all the
@ -111,6 +111,22 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">External Resources</label>
<div class="col-sm-10 form-control-static">
{% for extres in person.personextresource_set.all %}
<div class="row">
<div class="col-sm-1"><span title="{{ extres.name.name}}">{% firstof extres.display_name extres.name.name %}</span></div>
<div class="col-sm-11">{{extres.value}}
{% if forloop.first %}&nbsp;<a href="{% url 'ietf.ietfauth.views.edit_person_externalresources' %}"><span class="fa fa-pencil"></span></a>{% endif %}
</div>
</div>
{% empty %}
<div class="row"><div class="col-sm-1">None&nbsp;<a href="{% url 'ietf.ietfauth.views.edit_person_externalresources' %}"><span class="fa fa-pencil"></span></a></div></div>
{% endfor %}
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Email addresses</label>
<div class="col-sm-10">