diff --git a/physionet-django/console/templates/console/user_management.html b/physionet-django/console/templates/console/user_management.html
index f82f3863ea..270f36ad65 100644
--- a/physionet-django/console/templates/console/user_management.html
+++ b/physionet-django/console/templates/console/user_management.html
@@ -2,11 +2,21 @@
{% load static %}
+{% load user_templatetags %}
+
{% block title %}User management{% endblock %}
{% block content %}
+ {% if perms.self.invite_event_host %}
+
+ {% elif is_event_host %}
+
{{ subject.username }} is already an Event host.
+ {% endif %}
{{ subject.get_full_name }} ({{ subject.username }})
Profile
@@ -207,6 +217,5 @@
Credentialing history
No applications found.
{% endfor %}
-
{% endblock %}
diff --git a/physionet-django/console/urls.py b/physionet-django/console/urls.py
index 59f93f1692..af98a9beaf 100644
--- a/physionet-django/console/urls.py
+++ b/physionet-django/console/urls.py
@@ -159,6 +159,7 @@
path('event_agreements//delete/', views.event_agreement_delete, name='event_agreement_delete'),
path('event_agreements//new-version/', views.event_agreement_new_version,
name='event_agreement_new_version'),
+ path('console/user/manage//', views.event_invite_host, name='event_invite_host'),
# Courses/On Platform Training
path('courses/', training_views.courses, name='courses'),
diff --git a/physionet-django/console/views.py b/physionet-django/console/views.py
index f7cd7f4868..8714ac4dc4 100644
--- a/physionet-django/console/views.py
+++ b/physionet-django/console/views.py
@@ -3315,3 +3315,26 @@ def event_agreement_delete(request, pk):
messages.success(request, "The Event Agreement has been deleted.")
return redirect("event_agreement_list")
+
+
+@permission_required('user.invite_event_host', raise_exception=True)
+def event_invite_host(request, username):
+ """
+ Gives the user permissions to be an event host
+ """
+ try:
+ user = get_object_or_404(User, username=username)
+ group = Group.objects.get(name='Event Host')
+ is_event_host = user.groups.filter(name='Event Host').exists()
+
+ if not is_event_host and request.method == 'POST':
+ user.groups.add(group)
+ user.save()
+ messages.success(request, f"{user} has been added to the Event Host group.")
+ elif is_event_host:
+ messages.error(request, f"{user} is already an Event Host.")
+
+ except User.DoesNotExist:
+ messages.error(request, "User not found.")
+
+ return redirect(reverse('user_management', args=[username]))
diff --git a/physionet-django/events/migrations/0009_alter_event_options.py b/physionet-django/events/migrations/0009_alter_event_options.py
new file mode 100644
index 0000000000..9032560191
--- /dev/null
+++ b/physionet-django/events/migrations/0009_alter_event_options.py
@@ -0,0 +1,23 @@
+# Generated by Django 4.1.9 on 2023-11-17 20:27
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('events', '0008_alter_event_description'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='event',
+ options={
+ 'permissions': [
+ ('view_all_events', 'Can view all events in the console'),
+ ('invite_event_host', 'Can grant event host status to a user'),
+ ('view_event_menu', 'Can view event menu in the navbar'),
+ ]
+ },
+ ),
+ ]
diff --git a/physionet-django/events/models.py b/physionet-django/events/models.py
index 0c253c58b6..a6fbe22266 100644
--- a/physionet-django/events/models.py
+++ b/physionet-django/events/models.py
@@ -29,6 +29,7 @@ class Event(models.Model):
class Meta:
unique_together = ('title', 'host')
permissions = [('view_all_events', 'Can view all events in the console'),
+ ('invite_event_host', 'Can grant event host status to a user'),
('view_event_menu', 'Can view event menu in the navbar')]
def save(self, *args, **kwargs):