diff --git a/config/settings/base.py b/config/settings/base.py index 94b2f03df0d75b251a0564aecb60cb13bfa87c71..4d5367d01025e13cc112ffabd70874b3d356838c 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -97,6 +97,8 @@ EMBB_IGNORE_ADDRESSES = ['Mailer-Daemon@{fqdn}'.format(fqdn=SERVER_FQDN)] LVC_GROUP = 'Communities:LSCVirgoLIGOGroupMembers' LVEM_GROUP = 'gw-astronomy:LV-EM' LVEM_OBSERVERS_GROUP = 'gw-astronomy:LV-EM:Observers' +PUBLIC_GROUP = 'public_users' + # Executives group name EXEC_GROUP = 'executives' # EM Advocate group name @@ -111,6 +113,7 @@ ADMIN_MANAGED_GROUPS = [EM_ADVOCATE_GROUP, 'executives'] # Tag to apply to log messages to allow EM partners to view EXTERNAL_ACCESS_TAGNAME = 'lvem' +PUBLIC_ACCESS_TAGNAME = 'public' # FAR floor for outgoing VOEvents intended for GCN VOEVENT_FAR_FLOOR = 0 # Hz diff --git a/gracedb/core/permission_utils.py b/gracedb/core/permission_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..c24995e478d885205a97cee2db2d7be51d76282c --- /dev/null +++ b/gracedb/core/permission_utils.py @@ -0,0 +1,104 @@ +from django.conf import settings +from django.contrib.auth.models import Group + +from guardian.shortcuts import assign_perm, remove_perm + + +def assign_perms_to_obj(perms, group, obj): + """ + perms is a list of strings like ['view', 'annotate', 'add'] + """ + # Convert perms to a list of strings like + # {app_label}.{perm}_{model_name} + full_perm_fmt = '{app_label}.{perm}_{model_name}' + kwargs = { + 'app_label': obj._meta.app_label, + 'model_name': obj._meta.model_name, + } + full_perms = [full_perm_fmt.format(perm=p, **kwargs) for p in perms] + + # Assign all permissions + for perm in full_perms: + assign_perm(perm, group, obj) + + +def expose_event_or_superevent_to_lvem(obj): + """ + obj is an Event or Superevent instance. + + Currently works for superevents; will eventually be used for events + (once the permissions structure is overhauled. + """ + perms = ['view', 'annotate'] + + # Get LV-EM group + lvem_group = Group.objects.get(name=settings.LVEM_OBSERVERS_GROUP) + + # Assign permissions + assign_perms_to_obj(perms, lvem_group, obj) + + +def expose_event_or_superevent_to_public(obj): + """ + obj is an Event or Superevent instance. + + Currently works for superevents; will eventually be used for events + (once the permissions structure is overhauled. + """ + perms = ['view'] + + # Get public group + public_group = Group.objects.get(name=settings.PUBLIC_GROUP) + + # Assign permissions + assign_perms_to_obj(perms, public_group, obj) + + +def expose_log(log, group): + """ + Assigns group view permission ([app_label].view_[model_name]) permission to + log object. + """ + kwargs = { + 'app_label': log._meta.app_label, + 'model_name': log._meta.model_name, + } + permission = "{app_label}.view_{model_name}".format(**kwargs) + assign_perm(permission, group, log) + + +def expose_log_to_lvem(log): + """Applies expose_log for LV-EM Observers group""" + group = Group.objects.get(name=settings.LVEM_OBSERVERS_GROUP) + expose_log(log, group) + + +def expose_log_to_public(log): + """Applies expose_log for public group""" + group = Group.objects.get(name=settings.PUBLIC_GROUP) + expose_log(log, group) + + +def hide_log(log, group): + """ + Removes group view permission ([app_label].view_[model_name]) permission + from log object. + """ + kwargs = { + 'app_label': log._meta.app_label, + 'model_name': log._meta.model_name, + } + permission = "{app_label}.view_{model_name}".format(**kwargs) + remove_perm(permission, group, log) + + +def hide_log_from_lvem(log): + """Applies hide_log for LV-EM Observers group""" + group = Group.objects.get(name=settings.LVEM_OBSERVERS_GROUP) + hide_log(log, group) + + +def hide_log_from_public(log): + """Applies hide_log for public group""" + group = Group.objects.get(name=settings.PUBLIC_GROUP) + hide_log(log, group) diff --git a/gracedb/superevents/utils.py b/gracedb/superevents/utils.py index 049fd9d55319feb463d4181c1bfc71d5e749301e..beee5cc31b3fb2319761ba548f43ea9ef71c18fe 100644 --- a/gracedb/superevents/utils.py +++ b/gracedb/superevents/utils.py @@ -18,6 +18,8 @@ from alerts.superevent_utils import issue_alert_for_superevent_creation, \ from alerts.event_utils import issue_alert_for_event_log import os +from core.permission_utils import expose_log_to_lvem, expose_log_to_public, \ + hide_log_from_lvem, hide_log_from_public import logging logger = logging.getLogger(__name__) @@ -232,6 +234,21 @@ def add_tag_to_log(log, tag, user, add_log_message=True, issue_alert=False): # Add tag to log log.tags.add(tag) + # If this tag controls whether the log is exposed or not, we need to create + # a corresponding GroupObjectPermission. If we get to this point, + # permissions should have already been checked. + if (tag.name == settings.EXTERNAL_ACCESS_TAGNAME): + expose_log_to_lvem(log) + elif (tag.name == settings.PUBLIC_ACCESS_TAGNAME): + expose_log_to_public(log) + # Publicly exposed tags should also be exposed to LV-EM, if they + # aren't already + lvem_tag_applied = log.tags.filter( + name=settings.EXTERNAL_ACCESS_TAGNAME).exists() + if not lvem_tag_applied: + lvem_tag = Tag.objects.get(name=settings.EXTERNAL_ACCESS_TAGNAME) + add_tag_to_log(log, lvem_tag, user) + # Create log message to record tag addition? log_for_tag_addition = None if add_log_message: @@ -250,6 +267,21 @@ def remove_tag_from_log(log, tag, user, add_log_message=True, # Remove tag from log log.tags.remove(tag) + # If this tag controls whether the log is exposed or not, we need to create + # a corresponding GroupObjectPermission. If we get to this point, + # permissions should have already been checked. + if (tag.name == settings.EXTERNAL_ACCESS_TAGNAME): + hide_log_from_lvem(log) + # If the log is hidden from LV-EM, it should also be hidden from the + # public + public_tag_applied = log.tags.filter( + name=settings.PUBLIC_ACCESS_TAGNAME).exists() + if not public_tag_applied: + public_tag = Tag.objects.get(name=settings.PUBLIC_ACCESS_TAGNAME) + remove_tag_from_log(log, public_tag, user) + elif (tag.name == settings.PUBLIC_ACCESS_TAGNAME): + hide_log_from_public(log) + # Create log message to record tag removal? log_for_tag_removal = None if add_log_message: