Skip to content

Commit

Permalink
fix(ui/ingest): correct privilege used to show tab (#10483)
Browse files Browse the repository at this point in the history
Co-authored-by: Kunal-kankriya <[email protected]>
  • Loading branch information
anshbansal and Kunal-kankriya authored Jul 22, 2024
1 parent 9f570a7 commit 8b88930
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 11 deletions.
14 changes: 11 additions & 3 deletions datahub-web-react/src/app/ingest/ManageIngestionPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Tabs, Typography } from 'antd';
import React, { useState } from 'react';
import styled from 'styled-components';
import { IngestionSourceList } from './source/IngestionSourceList';
import { useAppConfig } from '../useAppConfig';
import { useUserContext } from '../context/useUserContext';
import { SecretsList } from './secret/SecretsList';
import { OnboardingTour } from '../onboarding/OnboardingTour';
import {
Expand Down Expand Up @@ -48,7 +50,13 @@ export const ManageIngestionPage = () => {
/**
* Determines which view should be visible: ingestion sources or secrets.
*/
const [selectedTab, setSelectedTab] = useState<TabType>(TabType.Sources);
const me = useUserContext();
const { config } = useAppConfig();
const isIngestionEnabled = config?.managedIngestionConfig.enabled;
const showIngestionTab = isIngestionEnabled && me && me.platformPrivileges?.manageIngestion;
const showSecretsTab = isIngestionEnabled && me && me.platformPrivileges?.manageSecrets;
const defaultTab = showIngestionTab ? TabType.Sources : TabType.Secrets;
const [selectedTab, setSelectedTab] = useState<TabType>(defaultTab);

const onClickTab = (newTab: string) => {
setSelectedTab(TabType[newTab]);
Expand All @@ -64,8 +72,8 @@ export const ManageIngestionPage = () => {
</Typography.Paragraph>
</PageHeaderContainer>
<StyledTabs activeKey={selectedTab} size="large" onTabClick={(tab: string) => onClickTab(tab)}>
<Tab key={TabType.Sources} tab={TabType.Sources} />
<Tab key={TabType.Secrets} tab={TabType.Secrets} />
{showIngestionTab && <Tab key={TabType.Sources} tab={TabType.Sources} />}
{showSecretsTab && <Tab key={TabType.Secrets} tab={TabType.Secrets} />}
</StyledTabs>
<ListContainer>{selectedTab === TabType.Sources ? <IngestionSourceList /> : <SecretsList />}</ListContainer>
</PageContainer>
Expand Down
4 changes: 2 additions & 2 deletions datahub-web-react/src/app/ingest/secret/SecretsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export const SecretsList = () => {
{
urn: res.data?.createSecret || '',
name: state.name,
description: state.description,
description: state.description || '',
},
client,
pageSize,
Expand All @@ -127,7 +127,7 @@ export const SecretsList = () => {
.catch((e) => {
message.destroy();
message.error({
content: `Failed to update ingestion source!: \n ${e.message || ''}`,
content: `Failed to update secret!: \n ${e.message || ''}`,
duration: 3,
});
});
Expand Down
2 changes: 1 addition & 1 deletion datahub-web-react/src/app/shared/admin/HeaderLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function HeaderLinks(props: Props) {
const showAnalytics = (isAnalyticsEnabled && me && me?.platformPrivileges?.viewAnalytics) || false;
const showSettings = true;
const showIngestion =
isIngestionEnabled && me && me.platformPrivileges?.manageIngestion && me.platformPrivileges?.manageSecrets;
isIngestionEnabled && me && (me.platformPrivileges?.manageIngestion || me.platformPrivileges?.manageSecrets);

useToggleEducationStepIdsAllowList(!!showIngestion, HOME_PAGE_INGESTION_ID);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ describe("ingestion source creation flow", () => {
// Go to ingestion page, create a snowflake source
cy.loginWithCredentials();
cy.goToIngestionPage();
cy.clickOptionWithId('[data-node-key="Sources"]');
cy.clickOptionWithTestId("create-ingestion-source-button");
cy.clickOptionWithText("Snowflake");
cy.waitTextVisible("Snowflake Details");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
const test_id = Math.floor(Math.random() * 100000);
const platform_policy_name = `Platform test policy ${test_id}`;
const number = Math.floor(Math.random() * 100000);
const name = `Example Name ${number}`;
const email = `example${number}@example.com`;

const tryToSignUp = () => {
cy.enterTextInTestId("email", email);
cy.enterTextInTestId("name", name);
cy.enterTextInTestId("password", "Example password");
cy.enterTextInTestId("confirmPassword", "Example password");
cy.mouseover("#title").click();
cy.waitTextVisible("Other").click();
cy.clickOptionWithId("[type=submit]");
return { name, email };
};

const signIn = () => {
cy.visit("/login");
cy.enterTextInTestId("username", email);
cy.enterTextInTestId("password", "Example password");
cy.clickOptionWithId("[type=submit]");
};

const updateAndSave = (Id, groupName, text) => {
cy.clickOptionWithTestId(Id).type(groupName);
cy.get(".rc-virtual-list").contains(text).click({ force: true });
cy.focused().blur();
};

const clickFocusAndType = (Id, text) => {
cy.clickOptionWithTestId(Id).focused().clear().type(text);
};

const clickOnButton = (saveButton) => {
cy.clickOptionWithId(`#${saveButton}`);
};

const createPolicy = (description, policyName) => {
clickFocusAndType("policy-description", description);
clickOnButton("nextButton");
updateAndSave("privileges", "Ingestion", "Manage Metadata Ingestion");
cy.wait(1000);
clickOnButton("nextButton");
updateAndSave("users", "All", "All Users");
clickOnButton("saveButton");
cy.waitTextVisible("Successfully saved policy.");
cy.ensureTextNotPresent("Successfully saved policy.");
cy.reload();
searchAndToggleMetadataPolicyStatus(policyName);
cy.get(".ant-table-row-level-0").contains(policyName);
};

const searchAndToggleMetadataPolicyStatus = (metadataPolicyName) => {
cy.get('[data-testid="search-input"]').should("be.visible");
cy.get('[data-testid="search-input"]').last().type(metadataPolicyName);
};

const editPolicy = (policyName, type, select) => {
searchAndToggleMetadataPolicyStatus(policyName);
cy.contains("tr", policyName).as("metadataPolicyRow");
cy.contains("EDIT").click();
clickOnButton("nextButton");
cy.clickOptionWithId(".ant-tag-close-icon");
updateAndSave("privileges", type, select);
clickOnButton("nextButton");
cy.clickOptionWithId(".ant-tag-close-icon");
updateAndSave("users", name, name);
clickOnButton("saveButton");
cy.waitTextVisible("Successfully saved policy.");
};

const deactivateExistingAllUserPolicies = () => {
cy.get(".ant-pagination li")
.its("length")
.then((len) => {
const pageCount = len - 2;
for (let page = 1; page <= pageCount; page++) {
cy.get("tbody tr td").should("be.visible");
cy.get("tbody tr").each(($row) => {
cy.wrap($row)
.find("td")
.eq(3)
.invoke("text")
.then((role) => {
if (role === "All Users") {
cy.wrap($row)
.find("td")
.eq(5)
.find("div button")
.eq(1)
.invoke("text")
.then((buttonText) => {
if (buttonText === "DEACTIVATE") {
cy.wrap($row)
.find("td")
.eq(5)
.find("div button")
.eq(1)
.click();
cy.waitTextVisible("Successfully deactivated policy.");
}
});
}
});
});
if (page < pageCount) {
cy.contains("li", `${page + 1}`).click();
cy.ensureTextNotPresent("No Policies");
}
}
});
};

describe("Manage Ingestion and Secret Privileges", () => {
let registeredEmail = "";
it("create Metadata Ingestion platform policy and assign privileges to all users", () => {
cy.loginWithCredentials();
cy.visit("/settings/permissions/policies");
cy.waitTextVisible("Manage Permissions");
cy.get(".ant-select-selection-item").should("be.visible").click();
cy.get(".ant-select-item-option-content").contains("All").click();
cy.get('[data-icon="delete"]').should("be.visible");
deactivateExistingAllUserPolicies();
cy.reload();
cy.clickOptionWithText("Create new policy");
clickFocusAndType("policy-name", platform_policy_name);
cy.clickOptionWithId('[data-testid="policy-type"] [title="Metadata"]');
cy.clickOptionWithTestId("platform");
createPolicy(
`Platform policy description ${test_id}`,
platform_policy_name,
);
cy.logout();
});

it("Create user and verify ingestion tab not present", () => {
cy.loginWithCredentials();
cy.visit("/settings/identities/users");
cy.waitTextVisible("Invite Users");
cy.clickOptionWithText("Invite Users");
cy.waitTextVisible(/signup\?invite_token=\w{32}/).then(($elem) => {
const inviteLink = $elem.text();
cy.log(inviteLink);
cy.visit("/settings/identities/users");
cy.logout();
cy.visit(inviteLink);
const { name, email } = tryToSignUp();
registeredEmail = email;
cy.waitTextVisible("Welcome to DataHub");
cy.hideOnboardingTour();
cy.waitTextVisible(name);
});
});

it("Edit Metadata Ingestion platform policy and assign privileges to the user", () => {
cy.loginWithCredentials();
cy.visit("/settings/permissions/policies");
cy.waitTextVisible("Manage Permissions");
editPolicy(platform_policy_name, "Ingestion", "Manage Metadata Ingestion");
});

it("Verify new user can see ingestion and access Manage Ingestion tab", () => {
cy.clearCookies();
cy.clearLocalStorage();
signIn();
cy.waitTextVisible("Welcome to DataHub");
cy.hideOnboardingTour();
cy.waitTextVisible(name);
cy.clickOptionWithText("Ingestion");
cy.wait(1000);
cy.get("body").click();
cy.waitTextVisible("Manage Data Sources");
cy.waitTextVisible("Sources");
cy.get(".ant-tabs-nav-list").contains("Source").should("be.visible");
cy.get(".ant-tabs-tab").should("have.length", 1);
});

it("Verify new user can see ingestion and access Manage Secret tab", () => {
cy.clearCookies();
cy.clearLocalStorage();
cy.loginWithCredentials();
cy.visit("/settings/permissions/policies");
cy.waitTextVisible("Manage Permissions");
editPolicy(platform_policy_name, "Secret", "Manage Secrets");
cy.logout();
signIn();
cy.waitTextVisible("Welcome to DataHub");
cy.hideOnboardingTour();
cy.waitTextVisible(name);
cy.clickOptionWithText("Ingestion");
cy.wait(1000);
cy.clickOptionWithId("body");
cy.waitTextVisible("Manage Data Sources");
cy.waitTextVisible("Secrets");
cy.get(".ant-tabs-nav-list").contains("Secrets").should("be.visible");
cy.get(".ant-tabs-tab").should("have.length", 1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ describe("managing secrets for ingestion creation", () => {
// Navigate to the manage ingestion page → secrets
cy.loginWithCredentials();
cy.goToIngestionPage();
cy.openEntityTab("Secrets");

// Create a new secret
cy.clickOptionWithTestId("create-secret-button");
Expand All @@ -28,6 +27,7 @@ describe("managing secrets for ingestion creation", () => {

// Create an ingestion source using a secret
cy.goToIngestionPage();
cy.clickOptionWithId('[data-node-key="Sources"]');
cy.get("#ingestion-create-source").click();
cy.clickOptionWithText("Snowflake");
cy.waitTextVisible("Snowflake Details");
Expand Down Expand Up @@ -60,10 +60,10 @@ describe("managing secrets for ingestion creation", () => {

// Remove ingestion source
cy.goToIngestionPage();
cy.get('[data-testid="delete-button"]').first().click();
cy.clickOptionWithId('[data-node-key="Sources"]');
cy.get('[aria-label="delete"]').first().click();
cy.waitTextVisible("Confirm Ingestion Source Removal");
cy.get("button").contains("Yes").click();
cy.waitTextVisible("Removed ingestion source.");
cy.ensureTextNotPresent(ingestion_source_name);

// Verify secret is not present during ingestion source creation for password dropdown
Expand Down Expand Up @@ -99,10 +99,10 @@ describe("managing secrets for ingestion creation", () => {

// Remove ingestion source and secret
cy.goToIngestionPage();
cy.get('[data-testid="delete-button"]').first().click();
cy.clickOptionWithId('[data-node-key="Sources"]');
cy.get('[aria-label="delete"]').first().click();
cy.waitTextVisible("Confirm Ingestion Source Removal");
cy.get("button").contains("Yes").click();
cy.waitTextVisible("Removed ingestion source.");
cy.ensureTextNotPresent(ingestion_source_name);
cy.clickOptionWithText("Secrets");
cy.waitTextVisible(`secretname${number}`);
Expand Down

0 comments on commit 8b88930

Please sign in to comment.