Repository: ckan/ckan

Issue:
Updating/Adding a Resource sets obj.url_changed = True to all other uploaded resources of the package
### CKAN Version if known (or site URL)
2.8.3 but as far as  tested it also happens in master

### Please describe the expected behaviour
Updating or adding a new resource to the package shouldn't set `obj.url_changed=True` in other resources with uploaded files of the same package.

### Please describe the actual behaviour
* Each time a resource is created if a file is uploaded, the `__init__` method of ResourceUpload sets the `resource['last_modified']` field.
* Later, each time a new resource is added to the Package (or an existing resource of that package edited) when executing `resource_dict_save` the `obj.url_changed` is set to true due to this condition: https://github.com/ckan/ckan/blob/f717999a1a4e63ecc192cb4dfe5a7506b7c8cff0/ckan/lib/dictization/model_save.py#L51

This causes the `IResourceURLChanged` interface to be notified even when nothing changed, but regardless that, it is confusing of why it is set to `True` if nothing changed on the resource.


### What steps can be taken to reproduce the issue? 
- Create a new CKAN instance
- Add a Package
- Add `resource_1` to it. *This resource should be a file to be uploaded*.
- Add a `resource_2` to the same package

This last action will call `resource_dict_save` for each resource of the package and when executing it for `resource_1`it will set `obj.url_changed` in the mentioned condition.


Discussion:
@pdelboca This is obviously a bug, and the problem is right above the line you linked:
https://github.com/ckan/ckan/blob/f717999a1a4e63ecc192cb4dfe5a7506b7c8cff0/ckan/lib/dictization/model_save.py#L48:L50

This assumes that `value` (ie the value of `resource['last_modified']`) is a string, but [that is not the case](https://github.com/ckan/ckan/blob/f717999a1a4e63ecc192cb4dfe5a7506b7c8cff0/ckan/lib/uploader.py#L222). And so the loop is never stopped if the dates are the same (ie the upload didn't change).

We need something like:

```diff
diff --git a/ckan/lib/dictization/model_save.py b/ckan/lib/dictization/model_save.py
index a9514e648..27f2f5542 100644
--- a/ckan/lib/dictization/model_save.py
+++ b/ckan/lib/dictization/model_save.py
@@ -46,7 +46,11 @@ def resource_dict_save(res_dict, context):
             continue
         if key in fields:
             if isinstance(getattr(obj, key), datetime.datetime):
-                if getattr(obj, key).isoformat() == value:
+                if isinstance(value, string_types):
+                    db_value = getattr(obj, key).isoformat()
+                else:
+                    db_value = getattr(obj, key)
+                if  db_value == value:
                     continue
                 if key == 'last_modified' and not new:
                     obj.url_changed = True
```

Can you submit a PR? This should be backported.

Great! I will submit the PR thanks!

Resolving patch:
diff --git a/ckan/lib/dictization/model_save.py b/ckan/lib/dictization/model_save.py
--- a/ckan/lib/dictization/model_save.py
+++ b/ckan/lib/dictization/model_save.py
@@ -46,7 +46,11 @@ def resource_dict_save(res_dict, context):
             continue
         if key in fields:
             if isinstance(getattr(obj, key), datetime.datetime):
-                if getattr(obj, key).isoformat() == value:
+                if isinstance(value, string_types):
+                    db_value = getattr(obj, key).isoformat()
+                else:
+                    db_value = getattr(obj, key)
+                if  db_value == value:
                     continue
                 if key == 'last_modified' and not new:
                     obj.url_changed = True


Test patch: