diff --git a/gracedb/urls.py b/gracedb/urls.py index 2c71cc045303582d9294927df9fbfa8157772beb..05649126763271184da2082d45e1324ab6deb7b5 100644 --- a/gracedb/urls.py +++ b/gracedb/urls.py @@ -25,7 +25,7 @@ urlpatterns = patterns('gracedb.views', url (r'^(?P<graceid>[GEHMT]\d+)/log/(?P<num>([\d]*|preview))$', 'logentry', name="logentry"), url (r'^(?P<graceid>[GEHMT]\d+)/embblog/(?P<num>([\d]*|preview))$', 'embblogentry', name="embblogentry"), url (r'^(?P<graceid>[GEHMT]\d+)/emobservation/(?P<num>([\d]*|preview))$', 'emobservation_entry', name="emobservation_entry"), - url (r'^(?P<graceid>[GEHMT]\d+)/log/(?P<num>\d+)/tag/(?P<tagname>.+)$', 'taglogentry', name="taglogentry"), + url (r'^(?P<graceid>[GEHMT]\d+)/log/(?P<num>\d+)/tag/(?P<tagname>.*)$', 'taglogentry', name="taglogentry"), # RDW Aug 2014 #(r'^admin/', include(admin.site.urls)), diff --git a/gracedb/views.py b/gracedb/views.py index 0e56897683235791fa3f4513d8cb05b40c63f891..edfd0c2d10cb21f2f82340977582d7be9290bd86 100644 --- a/gracedb/views.py +++ b/gracedb/views.py @@ -717,64 +717,77 @@ def latest(request): @event_and_auth_required def taglogentry(request, event, num, tagname): + # Note: this code is intertwined with the javascript in + # gracedb/templates/gracedb/event_detail_script.js, + # specifically lines 461-575, as of 2017/02/28. + + # Get relevant log entry eventlog = event.eventlog_set.filter(N=num)[0] if request.method == "POST": - try: - # Has this tag-eventlog relationship already been created? - tag = eventlog.tag_set.filter(name=tagname)[0] - msg = "Log already has tag %s" % tagname + # Handle cases where a user leaves the tagname blank. + if not tagname: + return HttpResponseBadRequest("Must specify a tagname.") + + # Check authorization - not allowed to touch 'lvem' tag on other + # users' entries. May want to restrict this more in the future. + if (is_external(request.user) and + tagname == settings.EXTERNAL_ACCESS_TAGNAME): + if request.user != eventlog.issuer: + msg = "You do not have permission to add or remove this tag." + return HttpResponseForbidden(msg) + + # Check if tag is already applied to this log entry. + tag_matches = eventlog.tag_set.filter(name=tagname) + if tag_matches: + msg = "Log already has tag %s." % tagname return HttpResponse(msg, content_type="text") - except: - # Check authorization - if is_external(request.user) and tagname == settings.EXTERNAL_ACCESS_TAGNAME: - if request.user != eventlog.issuer: - msg = "You do not have permission to add or remove this tag." - return HttpResponseForbidden(msg) - # Look for the tag. If it doesn't already exist, create it. - try: - tag = Tag.objects.filter(name=tagname)[0] - except: - displayName = request.POST['displayName'] - tag = Tag(name=tagname, displayName=displayName) - tag.save() + # Check if tag already exists in the database. If not, create it. + db_tags = Tag.objects.filter(name=tagname) + if not db_tags: + displayName = request.POST['displayName'] + tag = Tag(name=tagname, displayName=displayName) + tag.save() + else: + tag = db_tags[0] - # Now add the log message to this tag. - tag.eventlogs.add(eventlog) + # Now add the log message to this tag. + tag.eventlogs.add(eventlog) - # Create a log entry to document the tag creation. - msg = "Tagged message %s: %s " % (num, tagname) - logentry = EventLog(event=event, - issuer=request.user, - comment=msg) - try: - logentry.save() - except Exception as e: - msg = "Failed to save log entry documenting tag: " - msg = msg + str(e) + '\n' - msg = "The tag itself, however, is saved." - return HttpResponse(msg, content_type="text") - elif request.method == "DELETE": + # Create a log entry to document the tag creation. + msg = "Tagged message %s: %s " % (num, tagname) + logentry = EventLog(event=event, + issuer=request.user, + comment=msg) try: - # Has this tag-eventlog relationship already been created? - tag = eventlog.tag_set.filter(name=tagname)[0] - tag.eventlogs.remove(eventlog) - except: - msg = "Attempted to delete tag that doesn't exist." - return HttpResponseBadRequest(msg) - - # Check authorization - if is_external(request.user) and tagname == settings.EXTERNAL_ACCESS_TAGNAME: + logentry.save() + except Exception as e: + msg = "Failed to save log entry documenting tag: " + msg = msg + str(e) + '\n' + msg = "The tag itself, however, is saved." + return HttpResponse(msg, content_type="text") + elif request.method == "DELETE": + # STEP 1: Check authorization + if (is_external(request.user) and + tagname == settings.EXTERNAL_ACCESS_TAGNAME): if request.user != eventlog.issuer: msg = "You do not have permission to add or remove this tag." return HttpResponseForbidden(msg) + # Check if tag is applied to this log entry. + tags = eventlog.tag_set.filter(name=tagname) + if tags: + tag = tags[0] + tag.eventlogs.remove(eventlog) + else: + msg = "Attempted to delete tag that doesn't exist." + return HttpResponseBadRequest(msg) # Create a log entry to document the tag deletion. msg = "Removed tag %s for message %s. " % (tagname, num) logentry = EventLog(event=event, - issuer=request.user, - comment=msg) + issuer=request.user, + comment=msg) try: logentry.save() except Exception as e: @@ -786,7 +799,7 @@ def taglogentry(request, event, num, tagname): else: return HttpResponseBadRequest - # Hopefully, this will only ever be called form inside a script. Just in case... + # Hopefully, this will only ever be called from inside a script. Just in case... if not request.is_ajax(): return HttpResponseRedirect(reverse(view, args=[event.graceid()])) diff --git a/templates/gracedb/event_detail_script.js b/templates/gracedb/event_detail_script.js index 5bbaf0f5a53c43f1cc197285a240bc64dba06500..216375224e7b5b7e915503c983f32909db9cb502 100644 --- a/templates/gracedb/event_detail_script.js +++ b/templates/gracedb/event_detail_script.js @@ -465,23 +465,28 @@ require([ var actionBar = domConstruct.create("div", { "class": "dijitDialogPaneActionBar" }); var tbnode = domConstruct.create("div", { style: "margin: 0px auto 0px auto; text-align: center;" - }, actionBar); + }, actionBar); + var reload_page = false; var tagButton = new Button({ label: "Ok", onClick: function(){ - tagResultDialog.hide(); + tagResultDialog.hide(); + if (reload_page) { location.reload(true); } }}).placeAt(tbnode); request.del(tagUrl).then( function(text){ tagResultDialog.set("content", text); domConstruct.place(actionBar, tagResultDialog.containerNode); - tagResultDialog.show(); - location.reload(true); + tagResultDialog.show(); + reload_page = true; }, - function(error){ - tagResultDialog.set("content", "Error: " + error); + function(error){ + var err_msg = error; + if (error.response.text) { err_msg = error.response.text; } + tagResultDialog.set("content", "Error: " + err_msg); domConstruct.place(actionBar, tagResultDialog.containerNode); - tagResultDialog.show(); + tagResultDialog.show(); + reload_page = false; }); } } @@ -493,11 +498,13 @@ require([ var actionBar = domConstruct.create("div", { "class": "dijitDialogPaneActionBar" }); var tbnode = domConstruct.create("div", { style: "margin: 0px auto 0px auto; text-align: center;" - }, actionBar); + }, actionBar); + var reload_page = false; var tagButton = new Button({ label: "Ok", onClick: function(){ tagResultDialog.hide(); + if (reload_page) { location.reload(true); } } }).placeAt(tbnode); @@ -548,12 +555,15 @@ require([ tagResultDialog.set("content", text); domConstruct.place(actionBar, tagResultDialog.containerNode); tagResultDialog.show(); - location.reload(true); + reload_page = true; }, function(error){ - tagResultDialog.set("content", "Error: " + error); + var err_msg = error; + if (error.response.text) { err_msg = error.response.text; } + tagResultDialog.set("content", "Error: " + err_msg); domConstruct.place(actionBar, tagResultDialog.containerNode); - tagResultDialog.show(); + tagResultDialog.show(); + reload_page = false; } ); addTagDialog.hide();