We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Mixed view_only in multiple data_source_groups blocks query executions
A user belonging to multiple groups that have access to one data source but with different access levels can not execute queries on that data source.

For example, if a user belongs to built-in `default` group and you have set `view_only` for all data sources in this group to true, adding this user to a new group to allow full access to one of the data sources will not work.

This is caused by `group_level` definition in `def has_access()` in [permissions.py](https://github.com/getredash/redash/blob/master/redash/permissions.py):

```
required_level = 1 if need_view_only else 2
group_level = 1 if any(flatten([object_groups[group] for group in matching_groups])) else 2

return required_level <= group_level
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `redash/permissions.py`
Content:
```
1 from flask_login import current_user
2 from flask_restful import abort
3 import functools
4 from funcy import any, flatten
5 
6 view_only = True
7 not_view_only = False
8 
9 
10 def has_access(object_groups, user, need_view_only):
11     if 'admin' in user.permissions:
12         return True
13 
14     matching_groups = set(object_groups.keys()).intersection(user.groups)
15 
16     if not matching_groups:
17         return False
18 
19     required_level = 1 if need_view_only else 2
20     group_level = 1 if any(flatten([object_groups[group] for group in matching_groups])) else 2
21 
22     return required_level <= group_level
23 
24 
25 def require_access(object_groups, user, need_view_only):
26     if not has_access(object_groups, user, need_view_only):
27         abort(403)
28 
29 
30 class require_permissions(object):
31     def __init__(self, permissions):
32         self.permissions = permissions
33 
34     def __call__(self, fn):
35         @functools.wraps(fn)
36         def decorated(*args, **kwargs):
37             has_permissions = current_user.has_permissions(self.permissions)
38 
39             if has_permissions:
40                 return fn(*args, **kwargs)
41             else:
42                 abort(403)
43 
44         return decorated
45 
46 
47 def require_permission(permission):
48     return require_permissions((permission,))
49 
50 
51 def require_admin(fn):
52     return require_permission('admin')(fn)
53 
54 
55 def require_super_admin(fn):
56     return require_permission('super_admin')(fn)
57 
58 
59 def has_permission_or_owner(permission, object_owner_id):
60     return int(object_owner_id) == current_user.id or current_user.has_permission(permission)
61 
62 
63 def is_admin_or_owner(object_owner_id):
64     return has_permission_or_owner('admin', object_owner_id)
65 
66 
67 def require_permission_or_owner(permission, object_owner_id):
68     if not has_permission_or_owner(permission, object_owner_id):
69         abort(403)
70 
71 
72 def require_admin_or_owner(object_owner_id):
73     if not is_admin_or_owner(object_owner_id):
74         abort(403, message="You don't have permission to edit this resource.")
75
```
--- 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/redash/permissions.py b/redash/permissions.py
--- a/redash/permissions.py
+++ b/redash/permissions.py
@@ -17,7 +17,8 @@
         return False
 
     required_level = 1 if need_view_only else 2
-    group_level = 1 if any(flatten([object_groups[group] for group in matching_groups])) else 2
+
+    group_level = 1 if all(flatten([object_groups[group] for group in matching_groups])) else 2
 
     return required_level <= group_level

{"golden_diff": "diff --git a/redash/permissions.py b/redash/permissions.py\n--- a/redash/permissions.py\n+++ b/redash/permissions.py\n@@ -17,7 +17,8 @@\n         return False\n \n     required_level = 1 if need_view_only else 2\n-    group_level = 1 if any(flatten([object_groups[group] for group in matching_groups])) else 2\n+\n+    group_level = 1 if all(flatten([object_groups[group] for group in matching_groups])) else 2\n \n     return required_level <= group_level\n", "issue": "Mixed view_only in multiple data_source_groups blocks query executions\nA user belonging to multiple groups that have access to one data source but with different access levels can not execute queries on that data source.\n\nFor example, if a user belongs to built-in `default` group and you have set `view_only` for all data sources in this group to true, adding this user to a new group to allow full access to one of the data sources will not work.\n\nThis is caused by `group_level` definition in `def has_access()` in [permissions.py](https://github.com/getredash/redash/blob/master/redash/permissions.py):\n\n```\nrequired_level = 1 if need_view_only else 2\ngroup_level = 1 if any(flatten([object_groups[group] for group in matching_groups])) else 2\n\nreturn required_level <= group_level\n```\n\n", "before_files": [{"content": "from flask_login import current_user\nfrom flask_restful import abort\nimport functools\nfrom funcy import any, flatten\n\nview_only = True\nnot_view_only = False\n\n\ndef has_access(object_groups, user, need_view_only):\n    if 'admin' in user.permissions:\n        return True\n\n    matching_groups = set(object_groups.keys()).intersection(user.groups)\n\n    if not matching_groups:\n        return False\n\n    required_level = 1 if need_view_only else 2\n    group_level = 1 if any(flatten([object_groups[group] for group in matching_groups])) else 2\n\n    return required_level <= group_level\n\n\ndef require_access(object_groups, user, need_view_only):\n    if not has_access(object_groups, user, need_view_only):\n        abort(403)\n\n\nclass require_permissions(object):\n    def __init__(self, permissions):\n        self.permissions = permissions\n\n    def __call__(self, fn):\n        @functools.wraps(fn)\n        def decorated(*args, **kwargs):\n            has_permissions = current_user.has_permissions(self.permissions)\n\n            if has_permissions:\n                return fn(*args, **kwargs)\n            else:\n                abort(403)\n\n        return decorated\n\n\ndef require_permission(permission):\n    return require_permissions((permission,))\n\n\ndef require_admin(fn):\n    return require_permission('admin')(fn)\n\n\ndef require_super_admin(fn):\n    return require_permission('super_admin')(fn)\n\n\ndef has_permission_or_owner(permission, object_owner_id):\n    return int(object_owner_id) == current_user.id or current_user.has_permission(permission)\n\n\ndef is_admin_or_owner(object_owner_id):\n    return has_permission_or_owner('admin', object_owner_id)\n\n\ndef require_permission_or_owner(permission, object_owner_id):\n    if not has_permission_or_owner(permission, object_owner_id):\n        abort(403)\n\n\ndef require_admin_or_owner(object_owner_id):\n    if not is_admin_or_owner(object_owner_id):\n        abort(403, message=\"You don't have permission to edit this resource.\")\n", "path": "redash/permissions.py"}], "after_files": [{"content": "from flask_login import current_user\nfrom flask_restful import abort\nimport functools\nfrom funcy import any, flatten\n\nview_only = True\nnot_view_only = False\n\n\ndef has_access(object_groups, user, need_view_only):\n    if 'admin' in user.permissions:\n        return True\n\n    matching_groups = set(object_groups.keys()).intersection(user.groups)\n\n    if not matching_groups:\n        return False\n\n    required_level = 1 if need_view_only else 2\n\n    group_level = 1 if all(flatten([object_groups[group] for group in matching_groups])) else 2\n\n    return required_level <= group_level\n\n\ndef require_access(object_groups, user, need_view_only):\n    if not has_access(object_groups, user, need_view_only):\n        abort(403)\n\n\nclass require_permissions(object):\n    def __init__(self, permissions):\n        self.permissions = permissions\n\n    def __call__(self, fn):\n        @functools.wraps(fn)\n        def decorated(*args, **kwargs):\n            has_permissions = current_user.has_permissions(self.permissions)\n\n            if has_permissions:\n                return fn(*args, **kwargs)\n            else:\n                abort(403)\n\n        return decorated\n\n\ndef require_permission(permission):\n    return require_permissions((permission,))\n\n\ndef require_admin(fn):\n    return require_permission('admin')(fn)\n\n\ndef require_super_admin(fn):\n    return require_permission('super_admin')(fn)\n\n\ndef has_permission_or_owner(permission, object_owner_id):\n    return int(object_owner_id) == current_user.id or current_user.has_permission(permission)\n\n\ndef is_admin_or_owner(object_owner_id):\n    return has_permission_or_owner('admin', object_owner_id)\n\n\ndef require_permission_or_owner(permission, object_owner_id):\n    if not has_permission_or_owner(permission, object_owner_id):\n        abort(403)\n\n\ndef require_admin_or_owner(object_owner_id):\n    if not is_admin_or_owner(object_owner_id):\n        abort(403, message=\"You don't have permission to edit this resource.\")\n", "path": "redash/permissions.py"}]}