Repository: hydroshare/hydroshare

Issue:
Published resource missing published date
**Description of the bug**
I happened across a published resource that did not render.  I've included the logs from the error below.  This is caused by a published resource not having a published date.  I ran a query and identified two other resources that fail to render for the same reason.

```
>>> for ra in ResourceAccess.objects.filter(published=True).all():
...     if not ra.resource.metadata.dates.filter(type='published').all().first():
...         print(ra.resource.short_id)
...
d8f59a93f41d4074b61728eb46024713
231886df055e40f2a8186c16753f77f0
cf40bed6ddfe4a94977365105a4ffcec
```

Steps to reproduce the bug:
1. Go to https://hydroshare.org/resource/231886df055e40f2a8186c16753f77f0
2. See error

**Expected behavior**
The resource landing page should render without an error.

**Additional information**
```
[12/Oct/2022 20:08:55] ERROR [django.request:135] Internal Server Error: /resource/231886df055e40f2a8186c16753f77f0/
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 217, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 215, in _get_response
    response = response.render()
  File "/usr/local/lib/python3.6/site-packages/django/template/response.py", line 107, in render
    self.content = self.rendered_content
  File "/usr/local/lib/python3.6/site-packages/django/template/response.py", line 84, in rendered_content
    content = template.render(context, self._request)
  File "/usr/local/lib/python3.6/site-packages/django/template/backends/django.py", line 66, in render
    return self.template.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 207, in render
    return self._render(context)
  File "/usr/local/lib/python3.6/site-packages/django/test/utils.py", line 107, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py", line 177, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.6/site-packages/django/test/utils.py", line 107, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py", line 177, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.6/site-packages/django/test/utils.py", line 107, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py", line 177, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.6/site-packages/django/test/utils.py", line 107, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py", line 72, in render
    result = block.nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/defaulttags.py", line 322, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/defaulttags.py", line 322, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 1040, in render
    output = self.filter_expression.resolve(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 736, in resolve
    new_obj = func(obj, *arg_vals)
  File "/hydroshare/hs_core/templatetags/hydroshare_tags.py", line 80, in published_date
    return res_obj.metadata.dates.all().filter(type='published').first().start_date
AttributeError: 'NoneType' object has no attribute 'start_date'
```


Discussion:
plan to update this so that it logs out so we can tell what happened
https://github.com/hydroshare/hydroshare/blob/master/hs_core/views/__init__.py#L925

seems like it failed setting the date here:
https://github.com/hydroshare/hydroshare/blob/master/hs_core/hydroshare/resource.py#L1061
Ran this on Beta, looks like we have some other places where we "log" on the session...we might want to revise these

```
>>> from django.contrib.sessions.models import Session
>>> for s in Session.objects.all():
...     if "validation_error" in s.get_decoded().keys():
...             print(s.get_decoded())
... 
{'hs_tracking_id': 'REDACTED', '_auth_user_id': 'REDACTED', '_auth_user_backend': 'mezzanine.core.auth_backends.MezzanineBackend', '_auth_user_hash': 'REDACTED', 'validation_error': "Failed to create metadata element 'coverage'. ['Value for North latitude must be greater than or equal to that of South latitude.']."}
{'hs_tracking_id': 'REDACTED', '_auth_user_id': 'REDACTED', '_auth_user_backend': 'mezzanine.core.auth_backends.MezzanineBackend', '_auth_user_hash': 'REDACTED', 'validation_error': "Failed to create metadata element 'coverage'. ['Value for North latitude must be greater than or equal to that of South latitude.']."}
```
https://api.crossref.org/v1/works/10.4211/hs.d8f59a93f41d4074b61728eb46024713 (2022-10-05T04:07:36Z)
https://api.crossref.org/v1/works/10.4211/hs.231886df055e40f2a8186c16753f77f0 (2022-10-05T04:06:58Z)
https://api.crossref.org/v1/works/10.4211/hs.cf40bed6ddfe4a94977365105a4ffcec (2022-10-11T19:29:12Z)

Was hoping that these ^^^ Crossreff "created" dates would match the resource "updated" dates:
2022-10-17 14:08:10.654474+00:00
2022-10-17 10:18:36.173396+00:00
2022-10-17 06:21:19.221676+00:00
but no such luck...
It thought it was odd that these resources were updated TODAY, given that they can't really be accessed other than via api.
But then I realized that visiting the resource landing page for them is actually changing the "updated" date #facepalm.

Anyway, I guess we want to manually or via script, update the 3 resources with the Crossref dates, DOIs, and resource_modified.

Resolving patch:
diff --git a/hs_core/views/__init__.py b/hs_core/views/__init__.py
--- a/hs_core/views/__init__.py
+++ b/hs_core/views/__init__.py
@@ -499,14 +499,17 @@ def add_metadata_element(request, shortkey, element_name, *args, **kwargs):
                         except ValidationError as exp:
                             err_msg = err_msg.format(element_name, str(exp))
                             request.session['validation_error'] = err_msg
+                            logger.warn(err_msg)
                         except Error as exp:
                             # some database error occurred
                             err_msg = err_msg.format(element_name, str(exp))
                             request.session['validation_error'] = err_msg
+                            logger.warn(err_msg)
                         except Exception as exp:
                             # some other error occurred
                             err_msg = err_msg.format(element_name, str(exp))
                             request.session['validation_error'] = err_msg
+                            logger.warn(err_msg)
 
                     if is_add_success:
                         resource_modified(res, request.user, overwrite_bag=False)
@@ -613,10 +616,12 @@ def update_metadata_element(request, shortkey, element_name, element_id, *args,
                 except ValidationError as exp:
                     err_msg = err_msg.format(element_name, str(exp))
                     request.session['validation_error'] = err_msg
+                    logger.warn(err_msg)
                 except Error as exp:
                     # some database error occurred
                     err_msg = err_msg.format(element_name, str(exp))
                     request.session['validation_error'] = err_msg
+                    logger.warn(err_msg)
                 # TODO: it's brittle to embed validation logic at this level.
                 if element_name == 'title':
                     res.update_public_and_discoverable()
@@ -720,6 +725,7 @@ def delete_file(request, shortkey, f, *args, **kwargs):
         hydroshare.delete_resource_file(shortkey, f, user)  # calls resource_modified
     except ValidationError as err:
         request.session['validation_error'] = str(err)
+        logger.warn(str(err))
     finally:
         request.session['resource-mode'] = 'edit'
 
@@ -743,6 +749,7 @@ def delete_multiple_files(request, shortkey, *args, **kwargs):
         except ValidationError as err:
             request.session['resource-mode'] = 'edit'
             request.session['validation_error'] = str(err)
+            logger.warn(str(err))
             return HttpResponseRedirect(request.META['HTTP_REFERER'])
         except ObjectDoesNotExist as ex:
             # Since some specific resource types such as feature resource type delete all other
@@ -799,6 +806,7 @@ def delete_resource(request, shortkey, usertext, *args, **kwargs):
             return HttpResponseRedirect('/my-resources/')
         except ValidationError as ex:
             request.session['validation_error'] = str(ex)
+            logger.warn(str(ex))
             return HttpResponseRedirect(request.META['HTTP_REFERER'])
 
 
@@ -923,6 +931,7 @@ def publish(request, shortkey, *args, **kwargs):
         hydroshare.publish_resource(request.user, shortkey)
     except ValidationError as exp:
         request.session['validation_error'] = str(exp)
+        logger.warn(str(exp))
     else:
         request.session['just_published'] = True
     return HttpResponseRedirect(request.META['HTTP_REFERER'])


Test patch: