We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Some patch actions raise `ckan.logic.NotAuthorized` even though `context['ignore_auth'] = True`
## CKAN version

2.9+

## Describe the bug

The patch action functions in [ckan/logic/action/patch.py](https://github.com/ckan/ckan/tree/master/ckan/logic/action/patch.py) create a separate `show_context: Context` object that is used with a show action to retrieve the resource that is being patched. For almost all of these patch functions, the `'ignore_auth'` value from the patch action's input `context: Context` argument is not propagated to the `show_context` object. As a result, patching some resource types with `'ignore_auth': True` in the patch action's `Context` unexpectedly fails with a `ckan.logic.NotAuthorized` error.

Only [`package_patch()`](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L14) correctly propagates this value. The other four patch action functions are affected:

* [`resource_patch()`](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L57)
* [`group_patch()`](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L88)
* [`organization_patch()`](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L122)
* [`user_patch()`](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L157)

## Example

The following code snippet uses the Plugin Toolkit to access the [`user_patch()` function](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L157). This will fail if `user` is not authorized to perform `'user_show'`, because `'ignore_auth'` [is not propagated to `show_context`](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L171) in `user_patch()`.

```python
toolkit.get_action('user_patch')(
    context={
        'user': user,
        'ignore_auth': True,
    },
)
```

A problem like this showed up while I was modifying some code in the `ckanext-ldap` plugin. I believe the reason is that at the time this is being called, a currently not-logged-in user is being passed, and such a user cannot perform `'user_show'`. Regardless, I would have expected that with `'ignore_auth'` being passed into the patch function, the action would succeed, or at least would not return an authorization error.

## Suggested fix

### Easy

The easiest thing to do is just add `'ignore_auth': context.get('ignore_auth', False)` to each of the `show_context` definitions that are missing them.

### Robust

A more robust fix would be to introduce a helper function, `_create_show_context()` (defined below), that each function can call to create the `show_context` object. That way, future changes to the `show_context` will be propagated to all of the patch functions.

It is worth noting that I have absolutely no clue what the `'for_update'` key does. I couldn't find any documentation about it. It seems to be used in the database interaction code, but I'm not really familiar with working with databases. In any case: this key is not set consistently in the `show_context` objects across the various patch functions, so in the code below, it is an optional parameter that can be passed into the new function.

```python
def _create_show_context(context: Context, for_update: bool = False) -> Context:
    '''Create a Context that can be used with a user_show action call.

    This method is internal. It is meant to be used by the patch action
    functions to generate a Context that can be used with a show action
    corresponding to the type of the patch action. The show action is
    used to retrieve the item that will be patched.

    The ``show_context`` is derived from the original patch Context,
    which is the ``context`` input argument. Certain values are propagated
    from the input ``context`` to the returned ``show_context``.

    :param context: Context from the original patch request
    :type context: Context

    :param for_update: if ``True``, then ``show_context['for_update'] = True``.
        If ``False`` (the default), then ``'for_update'`` will not be
        explicitly set in ``show_context``.
    :type for_update: bool

    :returns: A Context, ``show_context``, with the appropriate settings.
    '''
    show_context: Context = {
        'model': context['model'],
        'session': context['session'],
        'user': context['user'],
        'auth_user_obj': context['auth_user_obj'],
        'ignore_auth': context.get('ignore_auth', False),
    }

    if for_update:
        show_context['for_update'] = True

    return show_context
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ckan/logic/action/patch.py`
Content:
```
1 # encoding: utf-8
2 
3 '''API functions for partial updates of existing data in CKAN'''
4 
5 from ckan.logic import (
6     get_action as _get_action,
7     check_access as _check_access,
8     get_or_bust as _get_or_bust,
9 )
10 from ckan.types import Context, DataDict
11 from ckan.types.logic import ActionResult
12 
13 
14 def package_patch(
15         context: Context, data_dict: DataDict) -> ActionResult.PackagePatch:
16     '''Patch a dataset (package).
17 
18     :param id: the id or name of the dataset
19     :type id: string
20 
21     The difference between the update and patch methods is that the patch will
22     perform an update of the provided parameters, while leaving all other
23     parameters unchanged, whereas the update methods deletes all parameters
24     not explicitly provided in the data_dict.
25 
26     You are able to partially update and/or create resources with
27     package_patch. If you are updating existing resources be sure to provide
28     the resource id. Existing resources excluded from the package_patch
29     data_dict will be removed. Resources in the package data_dict without
30     an id will be treated as new resources and will be added. New resources
31     added with the patch method do not create the default views.
32 
33     You must be authorized to edit the dataset and the groups that it belongs
34     to.
35     '''
36     _check_access('package_patch', context, data_dict)
37 
38     show_context: Context = {
39         'model': context['model'],
40         'session': context['session'],
41         'user': context['user'],
42         'auth_user_obj': context['auth_user_obj'],
43         'ignore_auth': context.get('ignore_auth', False),
44         'for_update': True
45     }
46 
47     package_dict = _get_action('package_show')(
48         show_context,
49         {'id': _get_or_bust(data_dict, 'id')})
50 
51     patched = dict(package_dict)
52     patched.update(data_dict)
53     patched['id'] = package_dict['id']
54     return _get_action('package_update')(context, patched)
55 
56 
57 def resource_patch(context: Context,
58                    data_dict: DataDict) -> ActionResult.ResourcePatch:
59     '''Patch a resource
60 
61     :param id: the id of the resource
62     :type id: string
63 
64     The difference between the update and patch methods is that the patch will
65     perform an update of the provided parameters, while leaving all other
66     parameters unchanged, whereas the update methods deletes all parameters
67     not explicitly provided in the data_dict
68     '''
69     _check_access('resource_patch', context, data_dict)
70 
71     show_context: Context = {
72         'model': context['model'],
73         'session': context['session'],
74         'user': context['user'],
75         'auth_user_obj': context['auth_user_obj'],
76         'for_update': True
77     }
78 
79     resource_dict = _get_action('resource_show')(
80         show_context,
81         {'id': _get_or_bust(data_dict, 'id')})
82 
83     patched = dict(resource_dict)
84     patched.update(data_dict)
85     return _get_action('resource_update')(context, patched)
86 
87 
88 def group_patch(context: Context,
89                 data_dict: DataDict) -> ActionResult.GroupPatch:
90     '''Patch a group
91 
92     :param id: the id or name of the group
93     :type id: string
94 
95     The difference between the update and patch methods is that the patch will
96     perform an update of the provided parameters, while leaving all other
97     parameters unchanged, whereas the update methods deletes all parameters
98     not explicitly provided in the data_dict
99     '''
100     _check_access('group_patch', context, data_dict)
101 
102     show_context: Context = {
103         'model': context['model'],
104         'session': context['session'],
105         'user': context['user'],
106         'auth_user_obj': context['auth_user_obj'],
107     }
108 
109     group_dict = _get_action('group_show')(
110         show_context,
111         {'id': _get_or_bust(data_dict, 'id')})
112 
113     patched = dict(group_dict)
114     patched.pop('display_name', None)
115     patched.update(data_dict)
116 
117     patch_context = context.copy()
118     patch_context['allow_partial_update'] = True
119     return _get_action('group_update')(patch_context, patched)
120 
121 
122 def organization_patch(
123         context: Context,
124         data_dict: DataDict) -> ActionResult.OrganizationPatch:
125     '''Patch an organization
126 
127     :param id: the id or name of the organization
128     :type id: string
129 
130     The difference between the update and patch methods is that the patch will
131     perform an update of the provided parameters, while leaving all other
132     parameters unchanged, whereas the update methods deletes all parameters
133     not explicitly provided in the data_dict
134     '''
135     _check_access('organization_patch', context, data_dict)
136 
137     show_context: Context = {
138         'model': context['model'],
139         'session': context['session'],
140         'user': context['user'],
141         'auth_user_obj': context['auth_user_obj'],
142     }
143 
144     organization_dict = _get_action('organization_show')(
145         show_context,
146         {'id': _get_or_bust(data_dict, 'id')})
147 
148     patched = dict(organization_dict)
149     patched.pop('display_name', None)
150     patched.update(data_dict)
151 
152     patch_context = context.copy()
153     patch_context['allow_partial_update'] = True
154     return _get_action('organization_update')(patch_context, patched)
155 
156 
157 def user_patch(context: Context,
158                data_dict: DataDict) -> ActionResult.UserPatch:
159     '''Patch a user
160 
161     :param id: the id or name of the user
162     :type id: string
163 
164     The difference between the update and patch methods is that the patch will
165     perform an update of the provided parameters, while leaving all other
166     parameters unchanged, whereas the update methods deletes all parameters
167     not explicitly provided in the data_dict
168     '''
169     _check_access('user_patch', context, data_dict)
170 
171     show_context: Context = {
172         'model': context['model'],
173         'session': context['session'],
174         'user': context['user'],
175         'auth_user_obj': context['auth_user_obj'],
176     }
177 
178     user_dict = _get_action('user_show')(
179         show_context,
180         {'id': _get_or_bust(data_dict, 'id')})
181 
182     patched = dict(user_dict)
183     patched.pop('display_name', None)
184     patched.update(data_dict)
185     return _get_action('user_update')(context, patched)
186
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ckan/logic/action/patch.py b/ckan/logic/action/patch.py
--- a/ckan/logic/action/patch.py
+++ b/ckan/logic/action/patch.py
@@ -6,6 +6,7 @@
     get_action as _get_action,
     check_access as _check_access,
     get_or_bust as _get_or_bust,
+    fresh_context as _fresh_context
 )
 from ckan.types import Context, DataDict
 from ckan.types.logic import ActionResult
@@ -68,13 +69,8 @@
     '''
     _check_access('resource_patch', context, data_dict)
 
-    show_context: Context = {
-        'model': context['model'],
-        'session': context['session'],
-        'user': context['user'],
-        'auth_user_obj': context['auth_user_obj'],
-        'for_update': True
-    }
+    show_context: Context = _fresh_context(context)
+    show_context.update({'for_update': True})
 
     resource_dict = _get_action('resource_show')(
         show_context,
@@ -99,12 +95,7 @@
     '''
     _check_access('group_patch', context, data_dict)
 
-    show_context: Context = {
-        'model': context['model'],
-        'session': context['session'],
-        'user': context['user'],
-        'auth_user_obj': context['auth_user_obj'],
-    }
+    show_context: Context = _fresh_context(context)
 
     group_dict = _get_action('group_show')(
         show_context,
@@ -134,12 +125,7 @@
     '''
     _check_access('organization_patch', context, data_dict)
 
-    show_context: Context = {
-        'model': context['model'],
-        'session': context['session'],
-        'user': context['user'],
-        'auth_user_obj': context['auth_user_obj'],
-    }
+    show_context: Context = _fresh_context(context)
 
     organization_dict = _get_action('organization_show')(
         show_context,
@@ -168,12 +154,7 @@
     '''
     _check_access('user_patch', context, data_dict)
 
-    show_context: Context = {
-        'model': context['model'],
-        'session': context['session'],
-        'user': context['user'],
-        'auth_user_obj': context['auth_user_obj'],
-    }
+    show_context: Context = _fresh_context(context)
 
     user_dict = _get_action('user_show')(
         show_context,

{"golden_diff": "diff --git a/ckan/logic/action/patch.py b/ckan/logic/action/patch.py\n--- a/ckan/logic/action/patch.py\n+++ b/ckan/logic/action/patch.py\n@@ -6,6 +6,7 @@\n     get_action as _get_action,\n     check_access as _check_access,\n     get_or_bust as _get_or_bust,\n+    fresh_context as _fresh_context\n )\n from ckan.types import Context, DataDict\n from ckan.types.logic import ActionResult\n@@ -68,13 +69,8 @@\n     '''\n     _check_access('resource_patch', context, data_dict)\n \n-    show_context: Context = {\n-        'model': context['model'],\n-        'session': context['session'],\n-        'user': context['user'],\n-        'auth_user_obj': context['auth_user_obj'],\n-        'for_update': True\n-    }\n+    show_context: Context = _fresh_context(context)\n+    show_context.update({'for_update': True})\n \n     resource_dict = _get_action('resource_show')(\n         show_context,\n@@ -99,12 +95,7 @@\n     '''\n     _check_access('group_patch', context, data_dict)\n \n-    show_context: Context = {\n-        'model': context['model'],\n-        'session': context['session'],\n-        'user': context['user'],\n-        'auth_user_obj': context['auth_user_obj'],\n-    }\n+    show_context: Context = _fresh_context(context)\n \n     group_dict = _get_action('group_show')(\n         show_context,\n@@ -134,12 +125,7 @@\n     '''\n     _check_access('organization_patch', context, data_dict)\n \n-    show_context: Context = {\n-        'model': context['model'],\n-        'session': context['session'],\n-        'user': context['user'],\n-        'auth_user_obj': context['auth_user_obj'],\n-    }\n+    show_context: Context = _fresh_context(context)\n \n     organization_dict = _get_action('organization_show')(\n         show_context,\n@@ -168,12 +154,7 @@\n     '''\n     _check_access('user_patch', context, data_dict)\n \n-    show_context: Context = {\n-        'model': context['model'],\n-        'session': context['session'],\n-        'user': context['user'],\n-        'auth_user_obj': context['auth_user_obj'],\n-    }\n+    show_context: Context = _fresh_context(context)\n \n     user_dict = _get_action('user_show')(\n         show_context,\n", "issue": "Some patch actions raise `ckan.logic.NotAuthorized` even though `context['ignore_auth'] = True`\n## CKAN version\r\n\r\n2.9+\r\n\r\n## Describe the bug\r\n\r\nThe patch action functions in [ckan/logic/action/patch.py](https://github.com/ckan/ckan/tree/master/ckan/logic/action/patch.py) create a separate `show_context: Context` object that is used with a show action to retrieve the resource that is being patched. For almost all of these patch functions, the `'ignore_auth'` value from the patch action's input `context: Context` argument is not propagated to the `show_context` object. As a result, patching some resource types with `'ignore_auth': True` in the patch action's `Context` unexpectedly fails with a `ckan.logic.NotAuthorized` error.\r\n\r\nOnly [`package_patch()`](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L14) correctly propagates this value. The other four patch action functions are affected:\r\n\r\n* [`resource_patch()`](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L57)\r\n* [`group_patch()`](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L88)\r\n* [`organization_patch()`](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L122)\r\n* [`user_patch()`](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L157)\r\n\r\n## Example\r\n\r\nThe following code snippet uses the Plugin Toolkit to access the [`user_patch()` function](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L157). This will fail if `user` is not authorized to perform `'user_show'`, because `'ignore_auth'` [is not propagated to `show_context`](https://github.com/ckan/ckan/blob/master/ckan/logic/action/patch.py#L171) in `user_patch()`.\r\n\r\n```python\r\ntoolkit.get_action('user_patch')(\r\n    context={\r\n        'user': user,\r\n        'ignore_auth': True,\r\n    },\r\n)\r\n```\r\n\r\nA problem like this showed up while I was modifying some code in the `ckanext-ldap` plugin. I believe the reason is that at the time this is being called, a currently not-logged-in user is being passed, and such a user cannot perform `'user_show'`. Regardless, I would have expected that with `'ignore_auth'` being passed into the patch function, the action would succeed, or at least would not return an authorization error.\r\n\r\n## Suggested fix\r\n\r\n### Easy\r\n\r\nThe easiest thing to do is just add `'ignore_auth': context.get('ignore_auth', False)` to each of the `show_context` definitions that are missing them.\r\n\r\n### Robust\r\n\r\nA more robust fix would be to introduce a helper function, `_create_show_context()` (defined below), that each function can call to create the `show_context` object. That way, future changes to the `show_context` will be propagated to all of the patch functions.\r\n\r\nIt is worth noting that I have absolutely no clue what the `'for_update'` key does. I couldn't find any documentation about it. It seems to be used in the database interaction code, but I'm not really familiar with working with databases. In any case: this key is not set consistently in the `show_context` objects across the various patch functions, so in the code below, it is an optional parameter that can be passed into the new function.\r\n\r\n```python\r\ndef _create_show_context(context: Context, for_update: bool = False) -> Context:\r\n    '''Create a Context that can be used with a user_show action call.\r\n\r\n    This method is internal. It is meant to be used by the patch action\r\n    functions to generate a Context that can be used with a show action\r\n    corresponding to the type of the patch action. The show action is\r\n    used to retrieve the item that will be patched.\r\n\r\n    The ``show_context`` is derived from the original patch Context,\r\n    which is the ``context`` input argument. Certain values are propagated\r\n    from the input ``context`` to the returned ``show_context``.\r\n\r\n    :param context: Context from the original patch request\r\n    :type context: Context\r\n\r\n    :param for_update: if ``True``, then ``show_context['for_update'] = True``.\r\n        If ``False`` (the default), then ``'for_update'`` will not be\r\n        explicitly set in ``show_context``.\r\n    :type for_update: bool\r\n\r\n    :returns: A Context, ``show_context``, with the appropriate settings.\r\n    '''\r\n    show_context: Context = {\r\n        'model': context['model'],\r\n        'session': context['session'],\r\n        'user': context['user'],\r\n        'auth_user_obj': context['auth_user_obj'],\r\n        'ignore_auth': context.get('ignore_auth', False),\r\n    }\r\n\r\n    if for_update:\r\n        show_context['for_update'] = True\r\n\r\n    return show_context\r\n```\n", "before_files": [{"content": "# encoding: utf-8\n\n'''API functions for partial updates of existing data in CKAN'''\n\nfrom ckan.logic import (\n    get_action as _get_action,\n    check_access as _check_access,\n    get_or_bust as _get_or_bust,\n)\nfrom ckan.types import Context, DataDict\nfrom ckan.types.logic import ActionResult\n\n\ndef package_patch(\n        context: Context, data_dict: DataDict) -> ActionResult.PackagePatch:\n    '''Patch a dataset (package).\n\n    :param id: the id or name of the dataset\n    :type id: string\n\n    The difference between the update and patch methods is that the patch will\n    perform an update of the provided parameters, while leaving all other\n    parameters unchanged, whereas the update methods deletes all parameters\n    not explicitly provided in the data_dict.\n\n    You are able to partially update and/or create resources with\n    package_patch. If you are updating existing resources be sure to provide\n    the resource id. Existing resources excluded from the package_patch\n    data_dict will be removed. Resources in the package data_dict without\n    an id will be treated as new resources and will be added. New resources\n    added with the patch method do not create the default views.\n\n    You must be authorized to edit the dataset and the groups that it belongs\n    to.\n    '''\n    _check_access('package_patch', context, data_dict)\n\n    show_context: Context = {\n        'model': context['model'],\n        'session': context['session'],\n        'user': context['user'],\n        'auth_user_obj': context['auth_user_obj'],\n        'ignore_auth': context.get('ignore_auth', False),\n        'for_update': True\n    }\n\n    package_dict = _get_action('package_show')(\n        show_context,\n        {'id': _get_or_bust(data_dict, 'id')})\n\n    patched = dict(package_dict)\n    patched.update(data_dict)\n    patched['id'] = package_dict['id']\n    return _get_action('package_update')(context, patched)\n\n\ndef resource_patch(context: Context,\n                   data_dict: DataDict) -> ActionResult.ResourcePatch:\n    '''Patch a resource\n\n    :param id: the id of the resource\n    :type id: string\n\n    The difference between the update and patch methods is that the patch will\n    perform an update of the provided parameters, while leaving all other\n    parameters unchanged, whereas the update methods deletes all parameters\n    not explicitly provided in the data_dict\n    '''\n    _check_access('resource_patch', context, data_dict)\n\n    show_context: Context = {\n        'model': context['model'],\n        'session': context['session'],\n        'user': context['user'],\n        'auth_user_obj': context['auth_user_obj'],\n        'for_update': True\n    }\n\n    resource_dict = _get_action('resource_show')(\n        show_context,\n        {'id': _get_or_bust(data_dict, 'id')})\n\n    patched = dict(resource_dict)\n    patched.update(data_dict)\n    return _get_action('resource_update')(context, patched)\n\n\ndef group_patch(context: Context,\n                data_dict: DataDict) -> ActionResult.GroupPatch:\n    '''Patch a group\n\n    :param id: the id or name of the group\n    :type id: string\n\n    The difference between the update and patch methods is that the patch will\n    perform an update of the provided parameters, while leaving all other\n    parameters unchanged, whereas the update methods deletes all parameters\n    not explicitly provided in the data_dict\n    '''\n    _check_access('group_patch', context, data_dict)\n\n    show_context: Context = {\n        'model': context['model'],\n        'session': context['session'],\n        'user': context['user'],\n        'auth_user_obj': context['auth_user_obj'],\n    }\n\n    group_dict = _get_action('group_show')(\n        show_context,\n        {'id': _get_or_bust(data_dict, 'id')})\n\n    patched = dict(group_dict)\n    patched.pop('display_name', None)\n    patched.update(data_dict)\n\n    patch_context = context.copy()\n    patch_context['allow_partial_update'] = True\n    return _get_action('group_update')(patch_context, patched)\n\n\ndef organization_patch(\n        context: Context,\n        data_dict: DataDict) -> ActionResult.OrganizationPatch:\n    '''Patch an organization\n\n    :param id: the id or name of the organization\n    :type id: string\n\n    The difference between the update and patch methods is that the patch will\n    perform an update of the provided parameters, while leaving all other\n    parameters unchanged, whereas the update methods deletes all parameters\n    not explicitly provided in the data_dict\n    '''\n    _check_access('organization_patch', context, data_dict)\n\n    show_context: Context = {\n        'model': context['model'],\n        'session': context['session'],\n        'user': context['user'],\n        'auth_user_obj': context['auth_user_obj'],\n    }\n\n    organization_dict = _get_action('organization_show')(\n        show_context,\n        {'id': _get_or_bust(data_dict, 'id')})\n\n    patched = dict(organization_dict)\n    patched.pop('display_name', None)\n    patched.update(data_dict)\n\n    patch_context = context.copy()\n    patch_context['allow_partial_update'] = True\n    return _get_action('organization_update')(patch_context, patched)\n\n\ndef user_patch(context: Context,\n               data_dict: DataDict) -> ActionResult.UserPatch:\n    '''Patch a user\n\n    :param id: the id or name of the user\n    :type id: string\n\n    The difference between the update and patch methods is that the patch will\n    perform an update of the provided parameters, while leaving all other\n    parameters unchanged, whereas the update methods deletes all parameters\n    not explicitly provided in the data_dict\n    '''\n    _check_access('user_patch', context, data_dict)\n\n    show_context: Context = {\n        'model': context['model'],\n        'session': context['session'],\n        'user': context['user'],\n        'auth_user_obj': context['auth_user_obj'],\n    }\n\n    user_dict = _get_action('user_show')(\n        show_context,\n        {'id': _get_or_bust(data_dict, 'id')})\n\n    patched = dict(user_dict)\n    patched.pop('display_name', None)\n    patched.update(data_dict)\n    return _get_action('user_update')(context, patched)\n", "path": "ckan/logic/action/patch.py"}], "after_files": [{"content": "# encoding: utf-8\n\n'''API functions for partial updates of existing data in CKAN'''\n\nfrom ckan.logic import (\n    get_action as _get_action,\n    check_access as _check_access,\n    get_or_bust as _get_or_bust,\n    fresh_context as _fresh_context\n)\nfrom ckan.types import Context, DataDict\nfrom ckan.types.logic import ActionResult\n\n\ndef package_patch(\n        context: Context, data_dict: DataDict) -> ActionResult.PackagePatch:\n    '''Patch a dataset (package).\n\n    :param id: the id or name of the dataset\n    :type id: string\n\n    The difference between the update and patch methods is that the patch will\n    perform an update of the provided parameters, while leaving all other\n    parameters unchanged, whereas the update methods deletes all parameters\n    not explicitly provided in the data_dict.\n\n    You are able to partially update and/or create resources with\n    package_patch. If you are updating existing resources be sure to provide\n    the resource id. Existing resources excluded from the package_patch\n    data_dict will be removed. Resources in the package data_dict without\n    an id will be treated as new resources and will be added. New resources\n    added with the patch method do not create the default views.\n\n    You must be authorized to edit the dataset and the groups that it belongs\n    to.\n    '''\n    _check_access('package_patch', context, data_dict)\n\n    show_context: Context = {\n        'model': context['model'],\n        'session': context['session'],\n        'user': context['user'],\n        'auth_user_obj': context['auth_user_obj'],\n        'ignore_auth': context.get('ignore_auth', False),\n        'for_update': True\n    }\n\n    package_dict = _get_action('package_show')(\n        show_context,\n        {'id': _get_or_bust(data_dict, 'id')})\n\n    patched = dict(package_dict)\n    patched.update(data_dict)\n    patched['id'] = package_dict['id']\n    return _get_action('package_update')(context, patched)\n\n\ndef resource_patch(context: Context,\n                   data_dict: DataDict) -> ActionResult.ResourcePatch:\n    '''Patch a resource\n\n    :param id: the id of the resource\n    :type id: string\n\n    The difference between the update and patch methods is that the patch will\n    perform an update of the provided parameters, while leaving all other\n    parameters unchanged, whereas the update methods deletes all parameters\n    not explicitly provided in the data_dict\n    '''\n    _check_access('resource_patch', context, data_dict)\n\n    show_context: Context = _fresh_context(context)\n    show_context.update({'for_update': True})\n\n    resource_dict = _get_action('resource_show')(\n        show_context,\n        {'id': _get_or_bust(data_dict, 'id')})\n\n    patched = dict(resource_dict)\n    patched.update(data_dict)\n    return _get_action('resource_update')(context, patched)\n\n\ndef group_patch(context: Context,\n                data_dict: DataDict) -> ActionResult.GroupPatch:\n    '''Patch a group\n\n    :param id: the id or name of the group\n    :type id: string\n\n    The difference between the update and patch methods is that the patch will\n    perform an update of the provided parameters, while leaving all other\n    parameters unchanged, whereas the update methods deletes all parameters\n    not explicitly provided in the data_dict\n    '''\n    _check_access('group_patch', context, data_dict)\n\n    show_context: Context = _fresh_context(context)\n\n    group_dict = _get_action('group_show')(\n        show_context,\n        {'id': _get_or_bust(data_dict, 'id')})\n\n    patched = dict(group_dict)\n    patched.pop('display_name', None)\n    patched.update(data_dict)\n\n    patch_context = context.copy()\n    patch_context['allow_partial_update'] = True\n    return _get_action('group_update')(patch_context, patched)\n\n\ndef organization_patch(\n        context: Context,\n        data_dict: DataDict) -> ActionResult.OrganizationPatch:\n    '''Patch an organization\n\n    :param id: the id or name of the organization\n    :type id: string\n\n    The difference between the update and patch methods is that the patch will\n    perform an update of the provided parameters, while leaving all other\n    parameters unchanged, whereas the update methods deletes all parameters\n    not explicitly provided in the data_dict\n    '''\n    _check_access('organization_patch', context, data_dict)\n\n    show_context: Context = _fresh_context(context)\n\n    organization_dict = _get_action('organization_show')(\n        show_context,\n        {'id': _get_or_bust(data_dict, 'id')})\n\n    patched = dict(organization_dict)\n    patched.pop('display_name', None)\n    patched.update(data_dict)\n\n    patch_context = context.copy()\n    patch_context['allow_partial_update'] = True\n    return _get_action('organization_update')(patch_context, patched)\n\n\ndef user_patch(context: Context,\n               data_dict: DataDict) -> ActionResult.UserPatch:\n    '''Patch a user\n\n    :param id: the id or name of the user\n    :type id: string\n\n    The difference between the update and patch methods is that the patch will\n    perform an update of the provided parameters, while leaving all other\n    parameters unchanged, whereas the update methods deletes all parameters\n    not explicitly provided in the data_dict\n    '''\n    _check_access('user_patch', context, data_dict)\n\n    show_context: Context = _fresh_context(context)\n\n    user_dict = _get_action('user_show')(\n        show_context,\n        {'id': _get_or_bust(data_dict, 'id')})\n\n    patched = dict(user_dict)\n    patched.pop('display_name', None)\n    patched.update(data_dict)\n    return _get_action('user_update')(context, patched)\n", "path": "ckan/logic/action/patch.py"}]}