prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <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
  ```
  
  
  </issue>
  <code>
  [start of redash/permissions.py]
  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 of redash/permissions.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: 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
  
verification_info: {"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"}]}