From 14592f7906368a8f01cd93b39807e428631c3339 Mon Sep 17 00:00:00 2001 From: Amit Upreti Date: Wed, 15 Feb 2023 12:43:19 -0500 Subject: [PATCH 01/14] Created a New Model to Support Event Agreements What is Event Agreements? -->Event Agreements are like DUAs but specific to Event. Idea behind creating a new model: My understanding is that each event will be assigned a Event Agreements and the event host can choose which Event Agreements to link to event. One assumption i made was we dont want two different event editors to be able to edit each others Event Agreements(So i tied each Event Agreements to the Event Agreements creator) So the reason i decided to create a new model instead of using the existing DUA are 1. To keep things simple 2. The existing DUAs are tied to project type like `database`,`software` etc. So to make them work for events, we would have to come up with weird hack. So i thought using a new model will be cleaner and simpler. --- physionet-django/events/models.py | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/physionet-django/events/models.py b/physionet-django/events/models.py index 2140fc901b..985c6433cb 100644 --- a/physionet-django/events/models.py +++ b/physionet-django/events/models.py @@ -6,6 +6,8 @@ from django.contrib.auth.models import Permission from events.enums import EventCategory from events import validators +from project.modelcomponents.fields import SafeHTMLField +from project.validators import validate_version class Event(models.Model): @@ -155,6 +157,37 @@ def withdraw(self, comment_to_applicant=None): self._apply_decision(self.EventApplicationStatus.WITHDRAWN, comment_to_applicant) +class EventAgreement(models.Model): + name = models.CharField(max_length=100) + slug = models.SlugField(max_length=120, unique=True) + version = models.CharField(max_length=15, default='', validators=[validate_version]) + is_active = models.BooleanField(default=True) + html_content = SafeHTMLField(default='') + access_template = SafeHTMLField(default='') + creator = models.ForeignKey("user.User", on_delete=models.CASCADE) + + class Meta: + default_permissions = ('add',) + unique_together = (('name', 'version', 'creator'),) + + def __str__(self): + return self.name + + +class EventAgreementSignature(models.Model): + """ + Log of user signing EventAgreement + """ + event = models.ForeignKey('events.Event', on_delete=models.CASCADE) + event_agreement = models.ForeignKey('events.EventAgreement', on_delete=models.CASCADE) + user = models.ForeignKey('user.User', on_delete=models.CASCADE, + related_name='event_agreement_signatures') + sign_datetime = models.DateTimeField(auto_now_add=True) + + class Meta: + default_permissions = () + + class EventDataset(models.Model): """ Captures information about datasets for events. From 8b292f814edb705e9c6f62035f058ba2b4b63848 Mon Sep 17 00:00:00 2001 From: Amit Upreti Date: Wed, 15 Feb 2023 12:46:08 -0500 Subject: [PATCH 02/14] Provide the Event Host access to Admin console Because historically we have been using Admin Console for stuff like creating DUA, license and the Event Agreement is kind of same, it makes sense to put the code behind admin console. So for that the first step is to provide the `Event Host` access to Admin console. This should not pose any security risk as all the other views or links in templates are secured by different permission check. So after this change, the `Event Host` should be able to admin console and only see the `Event Participant stuff`(The code for that is coming after this commit) --- physionet-django/user/fixtures/demo-user.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/physionet-django/user/fixtures/demo-user.json b/physionet-django/user/fixtures/demo-user.json index c4293d0190..e2688ac689 100644 --- a/physionet-django/user/fixtures/demo-user.json +++ b/physionet-django/user/fixtures/demo-user.json @@ -14553,6 +14553,11 @@ "view_event_menu", "events", "event" + ], + [ + "can_view_admin_console", + "user", + "user" ] ] } From 8049364ee357ef666ff0a97beaf414a263635d89 Mon Sep 17 00:00:00 2001 From: Amit Upreti Date: Wed, 15 Feb 2023 12:46:57 -0500 Subject: [PATCH 03/14] Create an EventAgreement form --- physionet-django/events/forms.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/physionet-django/events/forms.py b/physionet-django/events/forms.py index b675183de1..30819f01a4 100644 --- a/physionet-django/events/forms.py +++ b/physionet-django/events/forms.py @@ -1,10 +1,9 @@ from django import forms from events.widgets import DatePickerInput -from events.models import Event, EventApplication, EventDataset +from events.models import Event, EventApplication, EventAgreement, EventDataset from project.models import PublishedProject - class AddEventForm(forms.ModelForm): """ A form for adding events. @@ -73,3 +72,18 @@ class EventDatasetForm(forms.ModelForm): class Meta: model = EventDataset fields = ('dataset', 'access_type') + + +class EventAgreementForm(forms.ModelForm): + class Meta: + model = EventAgreement + fields = ( + 'name', + 'version', + 'slug', + 'is_active', + 'html_content', + 'access_template', + ) + labels = {'html_content': 'Content'} + From b0a4b90f5bacbe7531c9eef377726ea6266e78cb Mon Sep 17 00:00:00 2001 From: Amit Upreti Date: Wed, 15 Feb 2023 12:57:39 -0500 Subject: [PATCH 04/14] CRUD for Event Agreement Just like the DUAs, here i copied code from DUA CRUD stuff and refactored it to work for Event Agreement. Although this looks intimidating as we have quite a large number of lines of code, its just refactored code, and i figured breaking down the changes to each step of CRUD would take more time than refactoring, testing. So to speed things up, i made a giant commit. --- .../templates/console/console_navbar.html | 9 +- .../console/event_agreement_detail.html | 23 +++++ .../console/event_agreement_list.html | 93 ++++++++++++++++++ .../console/event_agreement_new_version.html | 23 +++++ physionet-django/console/urls.py | 7 +- physionet-django/console/views.py | 97 ++++++++++++++++++- 6 files changed, 247 insertions(+), 5 deletions(-) create mode 100644 physionet-django/console/templates/console/event_agreement_detail.html create mode 100644 physionet-django/console/templates/console/event_agreement_list.html create mode 100644 physionet-django/console/templates/console/event_agreement_new_version.html diff --git a/physionet-django/console/templates/console/console_navbar.html b/physionet-django/console/templates/console/console_navbar.html index 29248def66..6026a0df83 100644 --- a/physionet-django/console/templates/console/console_navbar.html +++ b/physionet-django/console/templates/console/console_navbar.html @@ -136,7 +136,7 @@ {% endif %} - {% if perms.project.add_dua or perms.project.add_codeofconduct or perms.project.add_license %} + {% if perms.project.add_dua or perms.project.add_codeofconduct or perms.project.add_license or perms.events.add_event %}