Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Dashboard Level Access : dashboard lists #10594

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
bd220fa
Add all dashboards permissions views
Aug 13, 2020
9ee4320
Fix format
Aug 13, 2020
a3059cf
Fix format
Aug 13, 2020
3558487
Add dashboard permission view on new dashboard
Aug 16, 2020
ab84aba
feat update dashboard permissions on update dashboard title
Aug 19, 2020
c79ff7b
Merge branch 'master' into feat/add_all_dashboards_permissions
Aug 19, 2020
55ad339
Fix tests after merge from upstream/master
Aug 19, 2020
fa3d6aa
fix: comment after_insert
amitmiran137 Aug 24, 2020
a887b38
fix: add apache license
amitmiran137 Aug 24, 2020
376beda
fix: readd after_insert
amitmiran137 Aug 24, 2020
94866d4
fix: pylint
amitmiran137 Aug 24, 2020
88fbc6f
Add all dashboards permissions views
Aug 13, 2020
0954592
Fix format
Aug 13, 2020
29f51f7
Fix format
Aug 13, 2020
3851de1
Add dashboard permission view on new dashboard
Aug 16, 2020
e2ad850
feat update dashboard permissions on update dashboard title
Aug 19, 2020
e604c0b
Fix tests after merge from upstream/master
Aug 19, 2020
6aa96ed
Add all dashboard access permission enforcement
Aug 26, 2020
5d560ec
Merge remote-tracking branch 'origin/feat/add_all_dashboards_permissi…
Aug 26, 2020
23d6618
Add dashboard access permission enforcement on get dashboard list
Aug 26, 2020
085bf2e
Removed duplicated file and migrate to use only one dashboard filter
Aug 27, 2020
8ff2fcb
Refactor dashboards test to be more understandable
Aug 27, 2020
84f9851
Refactor dashboards test to be more understandable
Aug 30, 2020
c07d0e2
Refactor dashboards test to be more understandable
Aug 30, 2020
f3edb1f
Merge remote-tracking branch 'upstream/master' into feat/all_dashboar…
Aug 30, 2020
56dec2a
Fix using wrong of copy dashboard lead to other tests to fail
Aug 30, 2020
a0a1189
fix: per-commit
Aug 30, 2020
ddb9b1a
fix: license
Aug 30, 2020
92a8a98
fix: pre-commit
Aug 30, 2020
6b75595
Add feature_flag to all dashboards permissions views
Aug 30, 2020
acf05cc
fix: lint by disable
Aug 30, 2020
036a168
fix: pre commit
Aug 30, 2020
17da52d
Revert "Add feature_flag to all dashboards permissions views"
Aug 30, 2020
6f63628
fix: pre commit
Aug 30, 2020
b50e347
fix : lint
Aug 30, 2020
2d7d4e0
fix : try to fix lint again :)
Aug 30, 2020
f66d5ae
fix : try to fix lint again :) :)
Aug 30, 2020
e7b3a37
Fix bad use dashboard level access feature flag
Aug 31, 2020
0013863
fix: pre-commit
Aug 31, 2020
733a441
Add feature_flag to dashboard filter and tests
Aug 31, 2020
7011c76
Add migration for dashboard_level_access
Sep 1, 2020
7b82a05
Add test config for dashboard level access
Sep 1, 2020
f08994b
Refactor move migration for dashboard_level_access to superset init p…
Sep 1, 2020
e766e1d
fix: pre-commit
Sep 1, 2020
3a308b1
chore: log feature flag status
amitmiran137 Sep 2, 2020
0dc2d4b
fix: wrong syntax and pre-commit
Sep 4, 2020
d709758
Merge remote-tracking branch 'upstream/master' into feat/add_all_dash…
Sep 7, 2020
e0fb864
chore: renaming and delete thee if is_dashboard_level_access_enabled
Sep 10, 2020
91bdefd
fix: create dashboard tests are working
Sep 11, 2020
766089f
fix: make more tests work
Sep 14, 2020
a1be9c8
fix: license
Sep 15, 2020
c376cb6
fix: few pre-commits
Sep 15, 2020
26378ca
fix: prevent cyclic import using PEP 563 -- Postponed Evaluation of A…
Sep 15, 2020
1509151
fix: delete dash arrange parse created dashboard
Sep 15, 2020
ca98ba8
Refactor add and delete permissions for dashboards
Sep 16, 2020
27e3ffa
Fix lint
Sep 17, 2020
4b5f966
Fix failed test
Sep 17, 2020
40f32ea
Fix failed test
Sep 17, 2020
65b228f
add positional arguments to pytest
Sep 17, 2020
f68eb3e
Merge branch 'master' into feat/add_all_dashboards_permissions
amitmiran137 Sep 17, 2020
aef1407
fix: as long as that database has dashboards test is valid
Sep 17, 2020
b11e26b
fix: no need to clean new users in dashboard api_tests.py
Sep 18, 2020
a933f61
fix: undo draft
Sep 18, 2020
a02c699
fix: pre-commit
Sep 18, 2020
50d685e
fix: pylint
Sep 18, 2020
1ea8344
fix: pylint additions
Sep 18, 2020
eb6e7e2
fix: pre-commit #532
Sep 18, 2020
c2ec36c
fix: fixesss linting and precommit
Sep 18, 2020
45f927f
fix: fix typing
Sep 18, 2020
7351254
fix: bed merge of feature_flags
Sep 18, 2020
ea85926
chore: remove unused import
Sep 18, 2020
31ab992
chore: remove experiment tox env
Sep 19, 2020
21b9aed
chore: remove unused test config
Sep 19, 2020
bf1b80c
refactor: remove skipIf and set feature flag in the tests in beginnin…
Sep 19, 2020
dabf9c0
Revert "refactor: remove skipIf and set feature flag in the tests in …
Sep 19, 2020
c1fa652
test: add github action for the feature
Sep 19, 2020
9410afa
fix: name the github action
Sep 19, 2020
51344c2
fix: make action work the right SUPERSET_CONFIG module path
Sep 19, 2020
298fd9a
fix: bad yaml syntax
Sep 19, 2020
8b40662
fix: missed changes
Sep 19, 2020
1fa663e
Merge remote-tracking branch 'upstream/master' into feature/dash_leve…
Sep 22, 2020
21a3ed2
refactor: remove all unrelated change to manager.py to remove overhea…
Sep 23, 2020
0190c02
chore: undo unrelevant change, moved to a separated PR
Sep 24, 2020
63c3295
Merge remote-tracking branch 'upstream/master' into feat/add_all_dash…
Sep 27, 2020
1ee44c2
Merge remote-tracking branch 'upstream/master' into feat/add_all_dash…
Sep 27, 2020
e09a206
Merge remote-tracking branch 'ofekNIelsen/feat/add_all_dashboards_per…
Sep 27, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
255 changes: 255 additions & 0 deletions .github/workflows/superset-python-dashboard-level-access.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
# Python unit tests
name: Feature Flag - Dashboard Level Access

on: [push, pull_request]

jobs:
test-postgres-presto:
runs-on: ubuntu-18.04
strategy:
matrix:
# run unit tests in multiple version just for fun
python-version: [3.8]
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.superset_test_config_dashboard_level_access
REDIS_PORT: 16379
SUPERSET__SQLALCHEMY_DATABASE_URI:
postgresql+psycopg2://superset:superset@127.0.0.1:15432/superset
SUPERSET__SQLALCHEMY_EXAMPLES_URI:
presto://localhost:15433/memory/default
services:
postgres:
image: postgres:10-alpine
env:
POSTGRES_USER: superset
POSTGRES_PASSWORD: superset
ports:
# Use custom ports for services to avoid accidentally connecting to
# GitHub action runner's default installations
- 15432:5432
presto:
image: prestosql/presto:339
env:
POSTGRES_USER: superset
POSTGRES_PASSWORD: superset
ports:
# Use custom ports for services to avoid accidentally connecting to
# GitHub action runner's default installations
- 15433:8080
redis:
image: redis:5-alpine
ports:
- 16379:6379
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2.1.1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
uses: apache-superset/cached-dependencies@b90713b
with:
run: |
apt-get-install
pip-upgrade
pip install -r requirements/testing.txt
setup-postgres
- name: Run celery
run: celery worker --app=superset.tasks.celery_app:app -Ofair -c 2 &
- name: Python unit tests (PostgreSQL)
run: |
./scripts/python_tests.sh
- name: Upload code coverage
run: |
bash <(curl -s https://codecov.io/bash) -cF python

test-postgres-hive:
runs-on: ubuntu-18.04
strategy:
matrix:
# run unit tests in multiple version just for fun
python-version: [3.7, 3.8]
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.superset_test_config_dashboard_level_access
REDIS_PORT: 16379
SUPERSET__SQLALCHEMY_DATABASE_URI:
postgresql+psycopg2://superset:superset@127.0.0.1:15432/superset
SUPERSET__SQLALCHEMY_EXAMPLES_URI: hive://localhost:10000/default
UPLOAD_FOLDER: /tmp/.superset/uploads/
services:
postgres:
image: postgres:10-alpine
env:
POSTGRES_USER: superset
POSTGRES_PASSWORD: superset
ports:
# Use custom ports for services to avoid accidentally connecting to
# GitHub action runner's default installations
- 15432:5432
redis:
image: redis:5-alpine
ports:
- 16379:6379
steps:
- uses: actions/checkout@v2
- name: Create csv upload directory
run: sudo mkdir -p /tmp/.superset/uploads
- name: Give write access to the csv upload directory
run: sudo chown -R $USER:$USER /tmp/.superset
- name: Start hadoop and hive
run: docker-compose -f scripts/databases/hive/docker-compose.yml up -d
- name: Setup Python
uses: actions/setup-python@v2.1.1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
uses: apache-superset/cached-dependencies@b90713b
with:
run: |
apt-get-install
pip-upgrade
pip install -r requirements/testing.txt
setup-postgres
- name: Run celery
run: celery worker --app=superset.tasks.celery_app:app -Ofair -c 2 &
- name: Python unit tests (PostgreSQL)
run: |
./scripts/python_tests.sh
- name: Upload code coverage
run: |
bash <(curl -s https://codecov.io/bash) -cF python

test-postgres:
runs-on: ubuntu-18.04
strategy:
matrix:
python-version: [3.7, 3.8]
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.superset_test_config_dashboard_level_access
REDIS_PORT: 16379
SUPERSET__SQLALCHEMY_DATABASE_URI:
postgresql+psycopg2://superset:superset@127.0.0.1:15432/superset
services:
postgres:
image: postgres:10-alpine
env:
POSTGRES_USER: superset
POSTGRES_PASSWORD: superset
ports:
# Use custom ports for services to avoid accidentally connecting to
# GitHub action runner's default installations
- 15432:5432
redis:
image: redis:5-alpine
ports:
- 16379:6379
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2.1.1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
uses: apache-superset/cached-dependencies@b90713b
with:
run: |
apt-get-install
pip-upgrade
pip install -r requirements/testing.txt
setup-postgres
- name: Run celery
run: celery worker --app=superset.tasks.celery_app:app -Ofair -c 2 &
- name: Python unit tests (PostgreSQL)
run: |
./scripts/python_tests.sh
- name: Upload code coverage
run: |
bash <(curl -s https://codecov.io/bash) -cF python

test-mysql:
runs-on: ubuntu-18.04
strategy:
matrix:
python-version: [3.7]
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.superset_test_config_dashboard_level_access
REDIS_PORT: 16379
SUPERSET__SQLALCHEMY_DATABASE_URI: |
mysql+mysqldb://superset:superset@127.0.0.1:13306/superset?charset=utf8mb4&binary_prefix=true
services:
mysql:
image: mysql:5.7
env:
MYSQL_ROOT_PASSWORD: root
ports:
- 13306:3306
redis:
image: redis:5-alpine
options: --entrypoint redis-server
ports:
- 16379:6379
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2.1.1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
uses: apache-superset/cached-dependencies@b90713b
with:
run: |
apt-get-install
pip-upgrade
pip install -r requirements/testing.txt
setup-mysql
- name: Run celery
run: celery worker --app=superset.tasks.celery_app:app -Ofair -c 2 &
- name: Python unit tests (MySQL)
run: |
./scripts/python_tests.sh
- name: Upload code coverage
run: |
bash <(curl -s https://codecov.io/bash) -cF python

test-sqlite:
runs-on: ubuntu-18.04
strategy:
matrix:
python-version: [3.7]
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.superset_test_config_dashboard_level_access
REDIS_PORT: 16379
SUPERSET__SQLALCHEMY_DATABASE_URI: |
sqlite:///${{ github.workspace }}/.temp/unittest.db
services:
redis:
image: redis:5-alpine
ports:
- 16379:6379
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2.1.1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
uses: apache-superset/cached-dependencies@b90713b
with:
run: |
apt-get-install
pip-upgrade
pip install -r requirements/testing.txt
mkdir ${{ github.workspace }}/.temp
- name: Run celery
run: celery worker --app=superset.tasks.celery_app:app -Ofair -c 2 &
- name: Python unit tests (SQLite)
run: |
./scripts/python_tests.sh
- name: Upload code coverage
run: |
bash <(curl -s https://codecov.io/bash) -cF python
8 changes: 8 additions & 0 deletions superset/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

from superset import app, appbuilder, security_manager
from superset.app import create_app
from superset.constants import Security as SecurityConsts
from superset.extensions import celery_app, db
from superset.utils import core as utils
from superset.utils.celery import session_scope
Expand Down Expand Up @@ -73,6 +74,13 @@ def init() -> None:
"""Inits the Superset application"""
appbuilder.add_permissions(update_perms=True)
security_manager.sync_role_definitions()
from superset import is_feature_enabled
from superset.dashbaord_level_access_initializer import (
InitDashboardLevelAccessCommand,
)

if is_feature_enabled(SecurityConsts.DASHBOARD_LEVEL_ACCESS_FEATURE):
InitDashboardLevelAccessCommand().run()


@superset.command()
Expand Down
1 change: 1 addition & 0 deletions superset/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ def _try_json_readsha( # pylint: disable=unused-argument
"TAGGING_SYSTEM": False,
"SQLLAB_BACKEND_PERSISTENCE": False,
"LISTVIEWS_DEFAULT_CARD_VIEW": False,
"DASHBOARD_LEVEL_ACCESS": False,
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move DASHBOARD_LEVEL_MODE=[""] as a config

# Set the default view to card/grid view if thumbnail support is enabled.
Expand Down
16 changes: 16 additions & 0 deletions superset/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,19 @@ class RouteMethod: # pylint: disable=too-few-public-methods
CRUD_SET = {ADD, LIST, EDIT, DELETE, ACTION_POST, SHOW}
RELATED_VIEW_SET = {ADD, LIST, EDIT, DELETE}
REST_MODEL_VIEW_CRUD_SET = {DELETE, GET, GET_LIST, POST, PUT, INFO}


class Security: # pylint: disable=too-few-public-methods
DASHBOARD_LEVEL_ACCESS_FEATURE = "DASHBOARD_LEVEL_ACCESS"

class AllDashboard:
VIEW_NAME = "all_dashboards"
ACCESS_PERMISSION_NAME = "can_access_dashboard"
EDIT_PERMISSION_NAME = "can_edit"

class Dashboard:
VIEW_NAME_FORMAT = "dashboard.[{obj.dashboard_title}](id:{obj.id})"
ACCESS_PERMISSION_NAME = "can_access_dashboard"

class AllDatasources:
VIEW_NAME = "all_datasource_access"
89 changes: 89 additions & 0 deletions superset/dashbaord_level_access_initializer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import logging

from flask_appbuilder.security.sqla.models import (
assoc_permissionview_role,
PermissionView,
Role,
ViewMenu,
)

from superset import db, security_manager
from superset.constants import Security as SecurityConsts
from superset.models.dashboard import Dashboard

logger = logging.getLogger(__name__)


class InitDashboardLevelAccessCommand: # pylint:disable=too-few-public-methods
def __init__(self) -> None:
self.__access_all_dashboards_permission_view = ( # pylint:disable=invalid-name
None
)
self.__session = db.session

def run(self) -> None:
self.__create_all_dashboards_permissions()
self.__add_all_dashboards_permissions_to_permitted_roles()
self.__create_permissions_for_current_dashboards()

def __create_all_dashboards_permissions( # pylint:disable=invalid-name
self,
) -> None:
logger.info("start create_all_dashboards_permissions")
self.__access_all_dashboards_permission_view = self.create_pmv()
logger.info("done create_all_dashboards_permissions")

@staticmethod
def create_pmv() -> PermissionView:
return security_manager.add_permission_view_menu(
SecurityConsts.AllDashboard.ACCESS_PERMISSION_NAME,
SecurityConsts.AllDashboard.VIEW_NAME,
)

def __add_all_dashboards_permissions_to_permitted_roles( # pylint:disable=invalid-name
self,
) -> None:
logger.info("start add_all_dashboards_permissions_to_permitted_roles")
roles = (
self.__session.query(Role)
.join(assoc_permissionview_role)
.join(PermissionView)
.join(ViewMenu)
.filter(
ViewMenu.name == SecurityConsts.AllDatasources.VIEW_NAME,
ViewMenu.name != SecurityConsts.AllDashboard.VIEW_NAME,
)
.all()
)
for role in roles:
role.permissions.append(self.__access_all_dashboards_permission_view)
self.__session.merge(role)
self.__session.commit()
logger.info("done add_all_dashboards_permissions_to_permitted_roles")

def __create_permissions_for_current_dashboards( # pylint:disable=invalid-name
self,
) -> None:
logger.info("start create_permissions_for_current_dashboards")
dashboards = self.__session.query(Dashboard).all()
for dashboard in dashboards:
security_manager.add_permission_view_menu(
SecurityConsts.Dashboard.ACCESS_PERMISSION_NAME, dashboard.view_name
)
logger.info("done create_permissions_for_current_dashboards")
Loading