Skip to content

Commit

Permalink
Feat/integration tests dashboards (#1560)
Browse files Browse the repository at this point in the history
### Feature or Bugfix
<!-- please choose -->
- Feature


### Detail
- Add integration tests for dashboards
- Remove `shareDashboard` unused API
- Small update to notebook tests to now use `set_env_params` util

### Relates
- #1546

### Note

For dashboard tests to run successfully the follow pre-requisite work
must be complete:
- QS Enterprise Account created in `session_env1` with Capacity Pricing
- QS Dashboard created with `dataall` QS Group having `Owner`
permissions
- And `dashboardId` added to the `testdata.json` as shown in `README`



### Security
Please answer the questions below briefly where applicable, or write
`N/A`. Based on
[OWASP 10](https://owasp.org/Top10/en/).

- Does this PR introduce or modify any input fields or queries - this
includes
fetching data from storage outside the application (e.g. a database, an
S3 bucket)?
  - Is the input sanitized?
- What precautions are you taking before deserializing the data you
consume?
  - Is injection prevented by parametrizing queries?
  - Have you ensured no `eval` or similar functions are used?
- Does this PR introduce any functionality or component that requires
authorization?
- How have you ensured it respects the existing AuthN/AuthZ mechanisms?
  - Are you logging failed auth attempts?
- Are you using or adding any cryptographic features?
  - Do you use a standard proven implementations?
  - Are the used keys controlled by the customer? Where are they stored?
- Are you introducing any new policies/roles/users?
  - Have you used the least-privilege principle? How?


By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license.
  • Loading branch information
noah-paige committed Sep 23, 2024
1 parent 93bd073 commit dcc3849
Show file tree
Hide file tree
Showing 12 changed files with 441 additions and 74 deletions.
12 changes: 0 additions & 12 deletions backend/dataall/modules/dashboards/api/mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import_dashboard,
reject_dashboard_share,
request_dashboard_share,
share_dashboard,
update_dashboard,
)

Expand Down Expand Up @@ -35,17 +34,6 @@
resolver=delete_dashboard,
)


shareDashboard = gql.MutationField(
name='shareDashboard',
type=gql.Ref('DashboardShare'),
args=[
gql.Argument(name='principalId', type=gql.NonNullableType(gql.String)),
gql.Argument(name='dashboardUri', type=gql.NonNullableType(gql.String)),
],
resolver=share_dashboard,
)

requestDashboardShare = gql.MutationField(
name='requestDashboardShare',
type=gql.Ref('DashboardShare'),
Expand Down
9 changes: 0 additions & 9 deletions backend/dataall/modules/dashboards/api/resolvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,6 @@ def list_dashboard_shares(
return DashboardShareService.list_dashboard_shares(uri=dashboardUri, data=filter)


def share_dashboard(
context: Context,
source: Dashboard,
principalId: str = None,
dashboardUri: str = None,
):
return DashboardShareService.share_dashboard(uri=dashboardUri, principal_id=principalId)


def delete_dashboard(context: Context, source, dashboardUri: str = None):
return DashboardService.delete_dashboard(uri=dashboardUri)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,24 +81,6 @@ def list_dashboard_shares(uri: str, data: dict):
data=data,
)

@staticmethod
@TenantPolicyService.has_tenant_permission(MANAGE_DASHBOARDS)
@ResourcePolicyService.has_resource_permission(SHARE_DASHBOARD)
def share_dashboard(uri: str, principal_id: str):
context = get_context()
with context.db_engine.scoped_session() as session:
dashboard = DashboardRepository.get_dashboard_by_uri(session, uri)
share = DashboardRepository.create_share(
session=session,
username=context.username,
dashboard=dashboard,
principal_id=principal_id,
init_status=DashboardShareStatus.APPROVED,
)

DashboardShareService._create_share_policy(session, principal_id, dashboard.dashboardUri)
return share

@staticmethod
def _change_share_status(share, status):
DashboardShareService._check_share_status(share)
Expand Down
34 changes: 0 additions & 34 deletions tests/modules/dashboards/test_dashboards.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,40 +263,6 @@ def test_request_dashboard_share(
)
assert len(response.data.searchDashboards['nodes']) == 0

response = client.query(
"""
mutation shareDashboard($dashboardUri:String!, $principalId:String!){
shareDashboard(dashboardUri:$dashboardUri, principalId:$principalId){
shareUri
status
}
}
""",
dashboardUri=dashboard.dashboardUri,
principalId=group2.name,
username=user.username,
groups=[group.name],
)
assert response.data.shareDashboard.shareUri

response = client.query(
"""
query searchDashboards($filter:DashboardFilter!){
searchDashboards(filter:$filter){
count
nodes{
dashboardUri
userRoleForDashboard
}
}
}
""",
filter={},
username=user2.username,
groups=[group2.name],
)
assert len(response.data.searchDashboards['nodes']) == 1


def test_delete_dashboard(client, env_fixture, db, user, group, module_mocker, dashboard, patch_es):
response = client.query(
Expand Down
9 changes: 9 additions & 0 deletions tests_new/integration_tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ Currently **we support only Cognito based deployments** but support for any IdP
}
},
"envs": {
"persistent_env1": {
"accountId": "...",
"region": "us-east-1"
},
"session_env1": {
"accountId": "...",
"region": "eu-central-1"
Expand All @@ -62,6 +66,11 @@ Currently **we support only Cognito based deployments** but support for any IdP
"accountId": "...",
"region": "eu-west-1"
}
},
"dashboards": {
"session_env1": {
"dashboardId": "..."
},
}
}
```
Expand Down
7 changes: 7 additions & 0 deletions tests_new/integration_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,18 @@ class Env:
region: str


@dataclass_json
@dataclass
class Dashboard:
dashboardId: str


@dataclass_json
@dataclass
class TestData:
users: dict[str, User]
envs: dict[str, Env]
dashboards: dict[str, Dashboard]


@pytest.fixture(scope='session', autouse=True)
Expand Down
6 changes: 5 additions & 1 deletion tests_new/integration_tests/core/environment/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,14 @@ def create_environment(client, name, group, organizationUri, awsAccountId, regio
'region': region,
'description': 'Created for integration testing',
'tags': tags,
'type': 'IntegrationTesting',
'parameters': [
{'key': 'notebooksEnabled', 'value': 'true'},
{'key': 'dashboardsEnabled', 'value': 'true'},
{'key': 'mlStudiosEnabled', 'value': 'false'},
{'key': 'pipelinesEnabled', 'value': 'true'},
{'key': 'omicsEnabled', 'value': 'true'},
],
'type': 'IntegrationTesting',
}
},
'query': f"""
Expand Down
47 changes: 47 additions & 0 deletions tests_new/integration_tests/modules/dashboards/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import pytest
from integration_tests.modules.dashboards.mutations import (
import_dashboard,
delete_dashboard,
request_dashboard_share,
reject_dashboard_share,
)
from integration_tests.modules.dashboards.queries import get_dashboard
from integration_tests.core.environment.utils import set_env_params


def create_dataall_dashboard(client, session_id, dashboard_id, env):
dashboard_input = {
'label': session_id,
'dashboardId': dashboard_id,
'environmentUri': env.environmentUri,
'description': 'integration test dashboard',
'SamlGroupName': env.SamlGroupName,
'tags': [session_id],
'terms': [],
}
ds = import_dashboard(client, dashboard_input)
return get_dashboard(client, ds.dashboardUri)


@pytest.fixture(scope='session')
def dashboard1(session_id, client1, session_env1, testdata):
set_env_params(client1, session_env1, dashboardsEnabled='true')
dashboardId = testdata.dashboards['session_env1'].dashboardId
ds = None
try:
ds = create_dataall_dashboard(client1, session_id, dashboardId, session_env1)
yield ds
finally:
if ds:
delete_dashboard(client1, ds.dashboardUri)


@pytest.fixture(scope='function')
def dashboard1_share(client1, client2, dashboard1, group2):
share = None
try:
share = request_dashboard_share(client2, dashboard1.dashboardUri, group2)
yield share
finally:
if share:
reject_dashboard_share(client1, share.shareUri)
108 changes: 108 additions & 0 deletions tests_new/integration_tests/modules/dashboards/mutations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# TODO: This file will be replaced by using the SDK directly

# # IF MONITORING ON (TODO)
# createQuicksightDataSourceSet (TODO)


def import_dashboard(client, input):
query = {
'operationName': 'importDashboard',
'variables': {'input': input},
'query': """
mutation importDashboard($input: ImportDashboardInput!) {
importDashboard(input: $input) {
dashboardUri
name
label
DashboardId
created
}
}
""",
}
response = client.query(query=query)
return response.data.importDashboard


def update_dashboard(client, input):
query = {
'operationName': 'updateDashboard',
'variables': {'input': input},
'query': """
mutation updateDashboard($input: UpdateDashboardInput!) {
updateDashboard(input: $input) {
dashboardUri
name
label
created
}
}
""",
}
response = client.query(query=query)
return response.data.importDashboard


def delete_dashboard(client, dashboardUri):
query = {
'operationName': 'deleteDashboard',
'variables': {'dashboardUri': dashboardUri},
'query': """
mutation deleteDashboard($dashboardUri: String!) {
deleteDashboard(dashboardUri: $dashboardUri)
}
""",
}
response = client.query(query=query)
return response.data.deleteDashboard


def request_dashboard_share(client, dashboardUri, principalId):
query = {
'operationName': 'requestDashboardShare',
'variables': {'dashboardUri': dashboardUri, 'principalId': principalId},
'query': """
mutation requestDashboardShare($dashboardUri: String!,$principalId: String!) {
requestDashboardShare(dashboardUri: $dashboardUri,principalId: $principalId) {
shareUri
status
}
}
""",
}
response = client.query(query=query)
return response.data.requestDashboardShare


def approve_dashboard_share(client, shareUri):
query = {
'operationName': 'approveDashboardShare',
'variables': {'shareUri': shareUri},
'query': """
mutation approveDashboardShare($shareUri: String!) {
approveDashboardShare(shareUri: $shareUri) {
shareUri
status
}
}
""",
}
response = client.query(query=query)
return response.data.approveDashboardShare


def reject_dashboard_share(client, shareUri):
query = {
'operationName': 'rejectDashboardShare',
'variables': {'shareUri': shareUri},
'query': """
mutation rejectDashboardShare($shareUri: String!) {
rejectDashboardShare(shareUri: $shareUri) {
shareUri
status
}
}
""",
}
response = client.query(query=query)
return response.data.rejectDashboardShare
Loading

0 comments on commit dcc3849

Please sign in to comment.