Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 0 additions & 126 deletions ietf/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
from ietf.nomcom.factories import NomComFactory, nomcom_kwargs_for_year
from ietf.person.factories import PersonFactory, random_faker, EmailFactory, PersonalApiKeyFactory
from ietf.person.models import Email, User
from ietf.stats.models import MeetingRegistration
from ietf.utils.mail import empty_outbox, outbox, get_payload_text
from ietf.utils.models import DumpInfo
from ietf.utils.test_utils import TestCase, login_testing_unauthorized, reload_db_objects
Expand Down Expand Up @@ -705,131 +704,6 @@ def test_api_v2_person_export_view(self):
self.assertEqual(data['ascii'], robot.ascii)
self.assertEqual(data['user']['email'], robot.user.email)

def test_api_new_meeting_registration(self):
meeting = MeetingFactory(type_id='ietf')
reg = {
'apikey': 'invalid',
'affiliation': "Alguma Corporação",
'country_code': 'PT',
'email': 'foo@example.pt',
'first_name': 'Foo',
'last_name': 'Bar',
'meeting': meeting.number,
'reg_type': 'hackathon',
'ticket_type': '',
'checkedin': 'False',
'is_nomcom_volunteer': 'False',
}
url = urlreverse('ietf.api.views.api_new_meeting_registration')
r = self.client.post(url, reg)
self.assertContains(r, 'Invalid apikey', status_code=403)
oidcp = PersonFactory(user__is_staff=True)
# Make sure 'oidcp' has an acceptable role
RoleFactory(name_id='robot', person=oidcp, email=oidcp.email(), group__acronym='secretariat')
key = PersonalApiKeyFactory(person=oidcp, endpoint=url)
reg['apikey'] = key.hash()
#
# Test valid POST
# FIXME: sometimes, there seems to be something in the outbox?
old_len = len(outbox)
r = self.client.post(url, reg)
self.assertContains(r, "Accepted, New registration, Email sent", status_code=202)
#
# Check outgoing mail
self.assertEqual(len(outbox), old_len + 1)
body = get_payload_text(outbox[-1])
self.assertIn(reg['email'], outbox[-1]['To'] )
self.assertIn(reg['email'], body)
self.assertIn('account creation request', body)
#
# Check record
obj = MeetingRegistration.objects.get(email=reg['email'], meeting__number=reg['meeting'])
for key in ['affiliation', 'country_code', 'first_name', 'last_name', 'person', 'reg_type', 'ticket_type', 'checkedin']:
self.assertEqual(getattr(obj, key), False if key=='checkedin' else reg.get(key) , "Bad data for field '%s'" % key)
#
# Test with existing user
person = PersonFactory()
reg['email'] = person.email().address
reg['first_name'] = person.first_name()
reg['last_name'] = person.last_name()
#
r = self.client.post(url, reg)
self.assertContains(r, "Accepted, New registration", status_code=202)
#
# There should be no new outgoing mail
self.assertEqual(len(outbox), old_len + 1)
#
# Test multiple reg types
reg['reg_type'] = 'remote'
reg['ticket_type'] = 'full_week_pass'
r = self.client.post(url, reg)
self.assertContains(r, "Accepted, New registration", status_code=202)
objs = MeetingRegistration.objects.filter(email=reg['email'], meeting__number=reg['meeting'])
self.assertEqual(len(objs), 2)
self.assertEqual(objs.filter(reg_type='hackathon').count(), 1)
self.assertEqual(objs.filter(reg_type='remote', ticket_type='full_week_pass').count(), 1)
self.assertEqual(len(outbox), old_len + 1)
#
# Test incomplete POST
drop_fields = ['affiliation', 'first_name', 'reg_type']
for field in drop_fields:
del reg[field]
r = self.client.post(url, reg)
self.assertContains(r, 'Missing parameters:', status_code=400)
err, fields = r.content.decode().split(':', 1)
missing_fields = [f.strip() for f in fields.split(',')]
self.assertEqual(set(missing_fields), set(drop_fields))

def test_api_new_meeting_registration_nomcom_volunteer(self):
'''Test that Volunteer is created if is_nomcom_volunteer=True
is submitted to API
'''
meeting = MeetingFactory(type_id='ietf')
reg = {
'apikey': 'invalid',
'affiliation': "Alguma Corporação",
'country_code': 'PT',
'meeting': meeting.number,
'reg_type': 'onsite',
'ticket_type': '',
'checkedin': 'False',
'is_nomcom_volunteer': 'False',
}
person = PersonFactory()
reg['email'] = person.email().address
reg['first_name'] = person.first_name()
reg['last_name'] = person.last_name()
now = datetime.datetime.now()
if now.month > 10:
year = now.year + 1
else:
year = now.year
# create appropriate group and nomcom objects
nomcom = NomComFactory.create(is_accepting_volunteers=True, **nomcom_kwargs_for_year(year))
url = urlreverse('ietf.api.views.api_new_meeting_registration')
oidcp = PersonFactory(user__is_staff=True)
# Make sure 'oidcp' has an acceptable role
RoleFactory(name_id='robot', person=oidcp, email=oidcp.email(), group__acronym='secretariat')
key = PersonalApiKeyFactory(person=oidcp, endpoint=url)
reg['apikey'] = key.hash()

# first test is_nomcom_volunteer False
r = self.client.post(url, reg)
self.assertContains(r, "Accepted, New registration", status_code=202)
# assert no Volunteers exists
self.assertEqual(Volunteer.objects.count(), 0)

# test is_nomcom_volunteer True
reg['is_nomcom_volunteer'] = 'True'
r = self.client.post(url, reg)
self.assertContains(r, "Accepted, Updated registration", status_code=202)
# assert Volunteer exists
self.assertEqual(Volunteer.objects.count(), 1)
volunteer = Volunteer.objects.last()
self.assertEqual(volunteer.person, person)
self.assertEqual(volunteer.nomcom, nomcom)
self.assertEqual(volunteer.origin, 'registration')

@override_settings(APP_API_TOKENS={"ietf.api.views.api_new_meeting_registration_v2": ["valid-token"]})
def test_api_new_meeting_registration_v2(self):
meeting = MeetingFactory(type_id='ietf')
Expand Down
1 change: 0 additions & 1 deletion ietf/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
url(r'^notify/session/polls/?$', meeting_views.api_upload_polls),
# Let the registration system notify us about registrations
url(r'^notify/meeting/registration/v2/?', api_views.api_new_meeting_registration_v2),
url(r'^notify/meeting/registration/?', api_views.api_new_meeting_registration),
# OpenID authentication provider
url(r'^openid/$', TemplateView.as_view(template_name='api/openid-issuer.html'), name='ietf.api.urls.oidc_issuer'),
url(r'^openid/', include('oidc_provider.urls', namespace='oidc_provider')),
Expand Down
95 changes: 0 additions & 95 deletions ietf/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
from django.contrib.auth import authenticate
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.http import HttpResponse, Http404, JsonResponse, HttpResponseBadRequest
from django.shortcuts import render, get_object_or_404
from django.urls import reverse
Expand All @@ -43,14 +41,11 @@
from ietf.doc.utils import DraftAliasGenerator, fuzzy_find_documents
from ietf.group.utils import GroupAliasGenerator, role_holder_emails
from ietf.ietfauth.utils import role_required
from ietf.ietfauth.views import send_account_creation_email
from ietf.ipr.utils import ingest_response_email as ipr_ingest_response_email
from ietf.meeting.models import Meeting
from ietf.meeting.utils import import_registration_json_validator, process_single_registration
from ietf.nomcom.models import Volunteer, NomCom
from ietf.nomcom.utils import ingest_feedback_email as nomcom_ingest_feedback_email
from ietf.person.models import Person, Email
from ietf.stats.models import MeetingRegistration
from ietf.sync.iana import ingest_review_email as iana_ingest_review_email
from ietf.utils import log
from ietf.utils.decorators import require_api_key
Expand Down Expand Up @@ -151,96 +146,6 @@ def post(self, request):
# else:
# return HttpResponse(status=405)

@require_api_key
@role_required('Robot')
@csrf_exempt
def api_new_meeting_registration(request):
'''REST API to notify the datatracker about a new meeting registration'''
def err(code, text):
return HttpResponse(text, status=code, content_type='text/plain')
required_fields = [ 'meeting', 'first_name', 'last_name', 'affiliation', 'country_code',
'email', 'reg_type', 'ticket_type', 'checkedin', 'is_nomcom_volunteer']
fields = required_fields + []
if request.method == 'POST':
# parameters:
# apikey:
# meeting
# name
# email
# reg_type (In Person, Remote, Hackathon Only)
# ticket_type (full_week, one_day, student)
#
data = {'attended': False, }
missing_fields = []
for item in fields:
value = request.POST.get(item, None)
if value is None and item in required_fields:
missing_fields.append(item)
data[item] = value
if missing_fields:
return err(400, "Missing parameters: %s" % ', '.join(missing_fields))
number = data['meeting']
try:
meeting = Meeting.objects.get(number=number)
except Meeting.DoesNotExist:
return err(400, "Invalid meeting value: '%s'" % (number, ))
reg_type = data['reg_type']
email = data['email']
try:
validate_email(email)
except ValidationError:
return err(400, "Invalid email value: '%s'" % (email, ))
if request.POST.get('cancelled', 'false') == 'true':
MeetingRegistration.objects.filter(
meeting_id=meeting.pk,
email=email,
reg_type=reg_type).delete()
return HttpResponse('OK', status=200, content_type='text/plain')
else:
object, created = MeetingRegistration.objects.get_or_create(
meeting_id=meeting.pk,
email=email,
reg_type=reg_type)
try:
# Update attributes
for key in set(data.keys())-set(['attended', 'apikey', 'meeting', 'email']):
if key == 'checkedin':
new = bool(data.get(key).lower() == 'true')
else:
new = data.get(key)
setattr(object, key, new)
person = Person.objects.filter(email__address=email)
if person.exists():
object.person = person.first()
object.save()
except ValueError as e:
return err(400, "Unexpected POST data: %s" % e)
response = "Accepted, New registration" if created else "Accepted, Updated registration"
if User.objects.filter(username__iexact=email).exists() or Email.objects.filter(address=email).exists():
pass
else:
send_account_creation_email(request, email)
response += ", Email sent"

# handle nomcom volunteer
if request.POST.get('is_nomcom_volunteer', 'false').lower() == 'true' and object.person:
try:
nomcom = NomCom.objects.get(is_accepting_volunteers=True)
except (NomCom.DoesNotExist, NomCom.MultipleObjectsReturned):
nomcom = None
if nomcom:
Volunteer.objects.get_or_create(
nomcom=nomcom,
person=object.person,
defaults={
"affiliation": data["affiliation"],
"origin": "registration"
}
)
return HttpResponse(response, status=202, content_type='text/plain')
else:
return HttpResponse(status=405)


@requires_api_token
@csrf_exempt
Expand Down
1 change: 1 addition & 0 deletions ietf/doc/views_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,7 @@ def sort_key(doc):
r.get_state_slug("draft-iesg") == "dead"
or r.get_state_slug("draft") == "repl"
or r.get_state_slug("draft") == "rfc"
or (r.get_state_slug("draft") == "expired" and r.get_state_slug("draft-iesg") == "idexists")
)
)
]
Expand Down
5 changes: 5 additions & 0 deletions ietf/meeting/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,13 +227,18 @@ def queryset(self, request, queryset):
if self.value():
return queryset.filter(meeting__id=self.value())
return queryset

class RegistrationTicketInline(admin.TabularInline):
model = RegistrationTicket

class RegistrationAdmin(admin.ModelAdmin):
model = Registration
# list_filter = [('meeting', Meeting.objects.filter(type='ietf')), ]
list_filter = [MeetingFilter, ]
list_display = ['meeting', 'first_name', 'last_name', 'affiliation', 'country_code', 'person', 'email', ]
search_fields = ['meeting__number', 'first_name', 'last_name', 'affiliation', 'country_code', 'email', ]
raw_id_fields = ['person']
inlines = [RegistrationTicketInline, ]
admin.site.register(Registration, RegistrationAdmin)

class RegistrationTicketAdmin(admin.ModelAdmin):
Expand Down
18 changes: 0 additions & 18 deletions ietf/meeting/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from .models import Meeting
from .utils import generate_proceedings_content
from .views import generate_agenda_data
from .utils import migrate_registrations, check_migrate_registrations
from .utils import fetch_attendance_from_meetings


Expand All @@ -18,23 +17,6 @@ def agenda_data_refresh():
generate_agenda_data(force_refresh=True)


@shared_task
def migrate_registrations_task(initial=False):
""" Migrate ietf.stats.MeetingRegistration to ietf.meeting.Registration
If initial is True, migrate all meetings otherwise only future meetings.
This function is idempotent. It can be run regularly from cron.
"""
migrate_registrations(initial=initial)


@shared_task
def check_migrate_registrations_task():
""" Compare MeetingRegistration with Registration to ensure
all records migrated
"""
check_migrate_registrations()


@shared_task
def proceedings_content_refresh_task(*, all=False):
"""Refresh meeting proceedings cache
Expand Down
Loading
Loading