mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-21 16:08:35 +00:00
Merge branch 'main' into invite-flow-part1/platform14
This commit is contained in:
commit
d2bc9dd1e5
29 changed files with 467 additions and 305 deletions
2
.version
2
.version
|
|
@ -1 +1 @@
|
|||
2.32.3
|
||||
2.32.5
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ module.exports = defineConfig({
|
|||
experimentalRunAllSpecs: true,
|
||||
baseUrl: "http://localhost:8082",
|
||||
specPattern: [
|
||||
"cypress/e2e/happypath/appbuilder/commonTestcases/**/*.cy.js",
|
||||
"cypress/e2e/happypath/appbuilder/ceTestcases/**/*.cy.js"
|
||||
"cypress/e2e/happyPath/appbuilder/commonTestcases/**/*.cy.js",
|
||||
"cypress/e2e/happyPath/appbuilder/ceTestcases/**/*.cy.js"
|
||||
],
|
||||
numTestsKeptInMemory: 1,
|
||||
redirectionLimit: 7,
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ module.exports = defineConfig({
|
|||
experimentalRunAllSpecs: true,
|
||||
baseUrl: "http://localhost:8082",
|
||||
specPattern: [
|
||||
"cypress/e2e/happypath/marketplace/commonTestcases/**/*.cy.js",
|
||||
"cypress/e2e/happypath/marketplace/ceTestcases/**/*.cy.js"
|
||||
"cypress/e2e/happyPath/marketplace/commonTestcases/**/*.cy.js",
|
||||
"cypress/e2e/happyPath/marketplace/ceTestcases/**/*.cy.js"
|
||||
],
|
||||
numTestsKeptInMemory: 1,
|
||||
redirectionLimit: 7,
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ module.exports = defineConfig({
|
|||
experimentalRunAllSpecs: true,
|
||||
baseUrl: "http://localhost:8082",
|
||||
specPattern: [
|
||||
"cypress/e2e/happypath/platform/commonTestcases/**/*.cy.js",
|
||||
"cypress/e2e/happypath/platform/ceTestcases/**/*.cy.js"
|
||||
"cypress/e2e/happyPath/platform/commonTestcases/**/*.cy.js",
|
||||
"cypress/e2e/happyPath/platform/ceTestcases/**/*.cy.js"
|
||||
],
|
||||
numTestsKeptInMemory: 1,
|
||||
redirectionLimit: 15,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ export const commonSelectors = {
|
|||
workspaceSettings: '[data-cy="workspace-settings"]',
|
||||
manageUsersOption: '[data-cy="users-list-item"]',
|
||||
manageGroupsOption: '[data-cy="groups-list-item"]',
|
||||
manageSSOOption: '[data-cy="sso-list-item"]',
|
||||
manageSSOOption: '[data-cy="workspace-login-list-item"]',
|
||||
workspaceVariableOption: '[data-cy="workspace-variables-list-item"]',
|
||||
clearFilterButton: '[data-cy="clear-filter-button"]',
|
||||
userStatusSelect: '[data-cy="user-status-select-continer"]',
|
||||
|
|
@ -257,6 +257,7 @@ export const commonSelectors = {
|
|||
},
|
||||
defaultModalTitle: '[data-cy="modal-title"]',
|
||||
workspaceConstantsIcon: '[data-cy="icon-workspace-constants"]',
|
||||
confirmationButton: '[data-cy="confirmation-button"]',
|
||||
};
|
||||
|
||||
export const commonWidgetSelector = {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
export const ssoSelector = {
|
||||
pagetitle: "[data-cy=manage-sso-page-title]",
|
||||
generalSettingsElements: {
|
||||
generalSettings: '[data-cy="general-settings-list-item"]',
|
||||
workspaceLoginPage: {
|
||||
enableSignupLabel: '[data-cy="enable-sign-up-label"]',
|
||||
helperText: "[data-cy=enable-sign-up-helper-text]",
|
||||
allowDefaultSSOLabel: '[data-cy="allow-default-sso-label"]',
|
||||
|
|
@ -10,16 +9,22 @@ export const ssoSelector = {
|
|||
allowedDomainHelperText: '[data-cy="allowed-domain-helper-text"]',
|
||||
workspaceLoginUrl: '[data-cy="workspace-login-url-label"]',
|
||||
workspaceLoginHelpText: '[data-cy="workspace-login-help-text"]',
|
||||
ssoHeader: '[data-cy="sso-header"]',
|
||||
instanceSSOHelperText: '[data-cy="instance-sso-helper-text"]',
|
||||
googleLabel: '[data-cy="google-label"]',
|
||||
githubLabel: '[data-cy="github-label"]',
|
||||
defaultSSO: '[data-cy="instance-sso-card"]',
|
||||
},
|
||||
cardTitle: "[data-cy=card-title]",
|
||||
enableSignUpToggle: '[data-cy="enable-sign-up-toggle"]',
|
||||
allowDefaultSSOToggle: '[data-cy="allow-default-sso-toggle"]',
|
||||
allowDefaultSSOToggle:
|
||||
'[style="padding-left: 0px; margin-bottom: 1px;"] > .switch > .slider',
|
||||
defaultSSOImage: '[data-cy="default-sso-status-image"]',
|
||||
allowedDomainInput: "[data-cy=allowed-domain-input]",
|
||||
allowedDomainInput: '[data-cy="allowed-domains"]',
|
||||
workspaceLoginUrl: '[data-cy="workspace-login-url"]',
|
||||
cancelButton: "[data-cy=cancel-button]",
|
||||
saveButton: "[data-cy=save-button]",
|
||||
google: '[data-cy="google-list-item"]',
|
||||
google: '[data-cy="google-sso-card"]',
|
||||
googleEnableToggle: '[data-cy="google-enable-toggle"]',
|
||||
statusLabel: "[data-cy=status-label]",
|
||||
clientIdLabel: "[data-cy=client-id-label]",
|
||||
|
|
@ -29,9 +34,9 @@ export const ssoSelector = {
|
|||
googleTile: '[data-cy="google-sign-in-text"]',
|
||||
googleIcon: "[data-cy=google-sso-icon]",
|
||||
googleSSOText: "[data-cy=google-sso-text]",
|
||||
git: '[data-cy="github-list-item"]',
|
||||
git: '[data-cy="github-sso-card"]',
|
||||
gitEnableToggle: '[data-cy="github-toggle-input"]',
|
||||
githubLabel: '[data-cy="github-toggle-label"]',
|
||||
githubLabel: '[data-cy="github-label"]',
|
||||
clientSecretLabel: "[data-cy=client-secret-label]",
|
||||
encriptedLabel: "[data-cy=encripted-label]",
|
||||
clientSecretInput: "[data-cy=client-secret-input]",
|
||||
|
|
@ -52,4 +57,6 @@ export const ssoSelector = {
|
|||
passwordLoginToggleLbale: '[data-cy="label-password-login"]',
|
||||
alertText: '[data-cy="alert-text"]',
|
||||
disablePasswordHelperText: '[data-cy="disable-password-helper-text"]',
|
||||
defaultGoogle: '[data-cy="dropdown-options-google"]',
|
||||
defaultGithub: '[data-cy="dropdown-options-git"]',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
export const ssoText = {
|
||||
pagetitle: " SSO",
|
||||
generalSettingsElements: {
|
||||
generalSettings: "General Settings",
|
||||
pagetitle: " Workspace login",
|
||||
workspaceLoginPage: {
|
||||
enableSignupLabel: "Enable Signup",
|
||||
helperText: "New account will be created for user's first time SSO sign in",
|
||||
allowDefaultSSOLabel: "Allow default SSO",
|
||||
|
|
@ -12,34 +11,39 @@ export const ssoText = {
|
|||
"Support multiple domains. Enter domain names separated by comma. example: tooljet.com,tooljet.io,yourorganization.com",
|
||||
workspaceLoginUrl: "Login URL",
|
||||
workspaceLoginHelpText: "Use this URL to login directly to this workspace",
|
||||
ssoHeader: "SSO",
|
||||
instanceSSOHelperText: "Display default SSO for workspace URL login",
|
||||
googleLabel: "Google",
|
||||
githubLabel: "GitHub",
|
||||
defaultSSO: "Default SSO",
|
||||
},
|
||||
cancelButton: "Cancel",
|
||||
saveButton: "Save changes",
|
||||
allowedDomain: "tooljet.io,gmail.com",
|
||||
ssoToast: "updated sso configurations",
|
||||
ssoToast: "Organization settings have been updated",
|
||||
ssoToast2: "updated SSO configurations",
|
||||
googleTitle: "Google",
|
||||
enabledLabel: "Enabled",
|
||||
googleEnabledToast: "Enabled Google SSO",
|
||||
googleSSOToast: "Saved Google SSO configurations",
|
||||
disabledLabel: "Disabled",
|
||||
googleDisableToast: "Disabled Google SSO",
|
||||
googleSSOText: "Sign in with Google",
|
||||
clientIdLabel: "Client Id",
|
||||
clientIdLabel: "Client ID",
|
||||
redirectUrlLabel: "Redirect URL",
|
||||
clientId: "24567098-mklj8t20za1smb2if.apps.googleusercontent.com",
|
||||
testClientId: "12345-client-id-.apps.googleusercontent.com",
|
||||
gitTitle: "GitHub",
|
||||
clientSecretLabel: "Client Secret",
|
||||
clientSecretLabel: "Client secret",
|
||||
encriptedLabel: "Encrypted",
|
||||
gitEnabledToast: "Enabled GitHub SSO",
|
||||
gitDisabledToast: "Disabled GitHub SSO",
|
||||
gitSSOToast: "Saved Git SSO configurations",
|
||||
gitSignInText: "Sign in with GitHub",
|
||||
passwordTitle: "Password Login",
|
||||
passwordEnabledToast: "Enabled Password login",
|
||||
passwordDisabledToast: "Disabled Password login",
|
||||
passwordDisabledToast: "Password login disabled successfully!",
|
||||
passwordDisableWarning:
|
||||
"Users won’t be able to login via username and password if password login is disabled. Please make sure that you have setup other authentication methods before disabling password login, do you want to continue?",
|
||||
hostNameLabel: "Host Name",
|
||||
"Disable password login only if you have configured SSO or else you will get locked out.",
|
||||
hostNameLabel: "Host name",
|
||||
hostNameHelpText: "Required if GitHub is self hosted",
|
||||
hostName: "Tooljet",
|
||||
signInHeader: "Sign in",
|
||||
|
|
@ -51,8 +55,8 @@ export const ssoText = {
|
|||
gitSignUpText: "Sign up with GitHub",
|
||||
gitUserStatusToast:
|
||||
"GitHub login failed - User does not exist in the workspace",
|
||||
passwordLoginToggleLbale: "Password login ",
|
||||
passwordLoginToggleLbale: "Password login",
|
||||
alertText: "Danger zone",
|
||||
disablePasswordHelperText:
|
||||
"Disable password login only if your SSO is configured otherwise you will get logged out.",
|
||||
"Disable password login only if your SSO is configured otherwise you will get locked out",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { commonSelectors } from "../../constants/selectors/common";
|
||||
import { commonText } from "../../constants/texts/common";
|
||||
import { commonSelectors } from "Selectors/common";
|
||||
import { commonText } from "Texts/common";
|
||||
import { fake } from "Fixtures/fake";
|
||||
import { addNewUser } from "Support/utils/onboarding";
|
||||
import { logout } from "Support/utils/common";
|
||||
|
|
|
|||
|
|
@ -11,10 +11,11 @@ describe("Manage SSO for multi workspace", () => {
|
|||
const envVar = Cypress.env("environment");
|
||||
beforeEach(() => {
|
||||
cy.defaultWorkspaceLogin();
|
||||
SSO.setSSOStatus("My workspace", "google", false);
|
||||
SSO.setSSOStatus("My workspace", "git", false);
|
||||
});
|
||||
it("Should verify General settings page elements", () => {
|
||||
common.navigateToManageSSO();
|
||||
|
||||
cy.get(commonSelectors.breadcrumbTitle).should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(
|
||||
commonText.breadcrumbworkspaceSettingTitle
|
||||
|
|
@ -27,14 +28,12 @@ describe("Manage SSO for multi workspace", () => {
|
|||
|
||||
cy.get(ssoSelector.cardTitle).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.generalSettingsElements.generalSettings
|
||||
"Workspace login"
|
||||
);
|
||||
for (const elements in ssoSelector.generalSettingsElements) {
|
||||
cy.get(
|
||||
ssoSelector.generalSettingsElements[elements]
|
||||
).verifyVisibleElement(
|
||||
cy.get(ssoSelector.workspaceLoginPage[elements]).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.generalSettingsElements[elements]
|
||||
ssoText.workspaceLoginPage[elements]
|
||||
);
|
||||
}
|
||||
cy.get(ssoSelector.enableSignUpToggle).should("be.visible");
|
||||
|
|
@ -51,12 +50,6 @@ describe("Manage SSO for multi workspace", () => {
|
|||
ssoText.saveButton
|
||||
);
|
||||
|
||||
SSO.generalSettings();
|
||||
|
||||
cy.get(ssoSelector.alertText).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.alertText
|
||||
);
|
||||
cy.get(ssoSelector.passwordEnableToggle).should("be.visible");
|
||||
cy.get(ssoSelector.passwordLoginToggleLbale).verifyVisibleElement(
|
||||
"have.text",
|
||||
|
|
@ -67,35 +60,32 @@ describe("Manage SSO for multi workspace", () => {
|
|||
ssoText.disablePasswordHelperText
|
||||
);
|
||||
|
||||
SSO.passwordPageElements();
|
||||
SSO.generalSettings();
|
||||
});
|
||||
|
||||
it("Should verify Google SSO page elements", () => {
|
||||
common.navigateToManageSSO();
|
||||
cy.get(ssoSelector.google).should("be.visible").click();
|
||||
cy.get(ssoSelector.cardTitle).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.googleTitle
|
||||
);
|
||||
cy.get(ssoSelector.cardTitle)
|
||||
.eq(1)
|
||||
.verifyVisibleElement("have.text", ssoText.googleTitle);
|
||||
cy.get(ssoSelector.googleEnableToggle).should("be.visible");
|
||||
cy.get(ssoSelector.clientIdLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.clientIdLabel
|
||||
);
|
||||
cy.get(ssoSelector.clientIdInput).should("be.visible");
|
||||
cy.get(ssoSelector.cancelButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.cancelButton
|
||||
);
|
||||
cy.get(ssoSelector.saveButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.saveButton
|
||||
);
|
||||
cy.get(ssoSelector.cancelButton)
|
||||
.eq(1)
|
||||
.verifyVisibleElement("have.text", ssoText.cancelButton);
|
||||
cy.get(ssoSelector.saveButton)
|
||||
.eq(1)
|
||||
.verifyVisibleElement("have.text", ssoText.saveButton);
|
||||
|
||||
SSO.googleSSOPageElements();
|
||||
SSO.disableDefaultSSO();
|
||||
SSO.visitWorkspaceLoginPage();
|
||||
|
||||
SSO.defaultSSO("My workspace", false);
|
||||
cy.logoutApi();
|
||||
cy.visit("/login/my-workspace");
|
||||
cy.get(ssoSelector.googleIcon).should("be.visible");
|
||||
cy.get(ssoSelector.googleSSOText).verifyVisibleElement(
|
||||
"have.text",
|
||||
|
|
@ -104,6 +94,8 @@ describe("Manage SSO for multi workspace", () => {
|
|||
});
|
||||
|
||||
it("Should verify Git SSO page elements", () => {
|
||||
SSO.defaultSSO("My workspace", true);
|
||||
|
||||
common.navigateToManageSSO();
|
||||
|
||||
cy.get(ssoSelector.git).should("be.visible").click();
|
||||
|
|
@ -139,27 +131,27 @@ describe("Manage SSO for multi workspace", () => {
|
|||
ssoText.encriptedLabel
|
||||
);
|
||||
cy.get(ssoSelector.clientSecretInput).should("be.visible");
|
||||
cy.get(ssoSelector.cancelButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.cancelButton
|
||||
);
|
||||
cy.get(ssoSelector.saveButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.saveButton
|
||||
);
|
||||
cy.get(ssoSelector.cancelButton)
|
||||
.eq(1)
|
||||
.verifyVisibleElement("have.text", ssoText.cancelButton);
|
||||
cy.get(ssoSelector.saveButton)
|
||||
.eq(1)
|
||||
.verifyVisibleElement("have.text", ssoText.saveButton);
|
||||
|
||||
SSO.gitSSOPageElements();
|
||||
SSO.visitWorkspaceLoginPage();
|
||||
SSO.defaultSSO("My workspace", false);
|
||||
cy.logoutApi();
|
||||
cy.visit("/login/my-workspace");
|
||||
|
||||
cy.get(ssoSelector.googleIcon).should("be.visible");
|
||||
cy.get(ssoSelector.googleSSOText).verifyVisibleElement(
|
||||
cy.get(ssoSelector.gitIcon).should("be.visible");
|
||||
cy.get(ssoSelector.gitSignInText).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.googleSSOText
|
||||
ssoText.gitSignInText
|
||||
);
|
||||
});
|
||||
|
||||
if (envVar === "Community") {
|
||||
it("Should verify the workspace login page", () => {
|
||||
it.skip("Should verify the workspace login page", () => {
|
||||
data.workspaceName = fake.companyName.toLowerCase();
|
||||
cy.apiLogin();
|
||||
cy.apiCreateWorkspace(data.workspaceName, data.workspaceName);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { dashboardSelector } from "Selectors/dashboard";
|
|||
import { updateWorkspaceName } from "Support/utils/userPermissions";
|
||||
import { groupsSelector } from "Selectors/manageGroups";
|
||||
import { groupsText } from "Texts/manageGroups";
|
||||
import { addNewUser } from "../../support/utils/onboarding";
|
||||
import { addNewUser } from "Support/utils/onboarding";
|
||||
|
||||
const data = {};
|
||||
data.groupName = fake.firstName.replaceAll("[^A-Za-z]", "");
|
||||
|
|
|
|||
|
|
@ -275,3 +275,11 @@ export const releaseApp = () => {
|
|||
cy.verifyToastMessage(commonSelectors.toastMessage, "Version v1 released");
|
||||
cy.wait(1000);
|
||||
};
|
||||
|
||||
export const verifyTooltipDisabled = (selector, message) => {
|
||||
cy.get(selector)
|
||||
.trigger("mouseover", { force: true })
|
||||
.then(() => {
|
||||
cy.get(".tooltip-inner").last().should("have.text", message);
|
||||
});
|
||||
};
|
||||
|
|
@ -6,207 +6,190 @@ import { commonText } from "Texts/common";
|
|||
import { dashboardSelector } from "Selectors/dashboard";
|
||||
|
||||
export const generalSettings = () => {
|
||||
cy.get(ssoSelector.enableSignUpToggle).then(($el) => {
|
||||
if ($el.is(":checked")) {
|
||||
cy.get(ssoSelector.enableSignUpToggle).uncheck();
|
||||
cy.get(ssoSelector.cancelButton).click();
|
||||
cy.get(ssoSelector.enableSignUpToggle).should("be.checked");
|
||||
} else {
|
||||
cy.get(ssoSelector.enableSignUpToggle).check();
|
||||
cy.get(ssoSelector.cancelButton).click();
|
||||
cy.get(ssoSelector.enableSignUpToggle).should("not.be.checked");
|
||||
cy.get(ssoSelector.enableSignUpToggle).check();
|
||||
}
|
||||
cy.get(ssoSelector.allowDefaultSSOToggle).then(($el) => {
|
||||
if ($el.is(":checked")) {
|
||||
cy.get(ssoSelector.allowDefaultSSOToggle).uncheck();
|
||||
cy.get(ssoSelector.cancelButton).click();
|
||||
cy.get(ssoSelector.allowDefaultSSOToggle).should("not.be.checked");
|
||||
} else {
|
||||
cy.get(ssoSelector.allowDefaultSSOToggle).check();
|
||||
cy.get(ssoSelector.cancelButton).click();
|
||||
cy.get(ssoSelector.allowDefaultSSOToggle).should("be.checked");
|
||||
cy.get(ssoSelector.allowDefaultSSOToggle).check();
|
||||
}
|
||||
});
|
||||
cy.clearAndType(ssoSelector.allowedDomainInput, ssoText.allowedDomain);
|
||||
cy.get(ssoSelector.saveButton).click();
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.ssoToast);
|
||||
});
|
||||
cy.get(ssoSelector.enableSignUpToggle).check();
|
||||
cy.get(ssoSelector.cancelButton).click();
|
||||
cy.get(ssoSelector.enableSignUpToggle).should("not.be.checked");
|
||||
cy.get(ssoSelector.enableSignUpToggle).check();
|
||||
cy.get(ssoSelector.saveButton).click();
|
||||
cy.get(ssoSelector.enableSignUpToggle).should("be.checked");
|
||||
|
||||
cy.get(ssoSelector.enableSignUpToggle).uncheck();
|
||||
cy.get(ssoSelector.saveButton).click();
|
||||
cy.get(ssoSelector.enableSignUpToggle).should("not.be.checked");
|
||||
|
||||
cy.get(ssoSelector.workspaceLoginPage.defaultSSO).click();
|
||||
cy.get(ssoSelector.defaultGoogle).verifyVisibleElement("have.text", "Google");
|
||||
cy.get(ssoSelector.defaultGithub).verifyVisibleElement("have.text", "Github");
|
||||
|
||||
cy.clearAndType(ssoSelector.allowedDomainInput, ssoText.allowedDomain);
|
||||
cy.get(ssoSelector.saveButton).click();
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.ssoToast);
|
||||
|
||||
cy.get(ssoSelector.passwordEnableToggle).uncheck();
|
||||
cy.get(commonSelectors.modalComponent).should("be.visible");
|
||||
cy.get(commonSelectors.modalMessage).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.passwordDisableWarning
|
||||
);
|
||||
cy.get(commonSelectors.cancelButton).eq(1).click();
|
||||
cy.get(ssoSelector.passwordEnableToggle).uncheck();
|
||||
cy.get(commonSelectors.confirmationButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.passwordDisabledToast
|
||||
);
|
||||
|
||||
cy.get(ssoSelector.passwordEnableToggle).check();
|
||||
cy.get(commonSelectors.saveButton).click();
|
||||
|
||||
cy.get(ssoSelector.allowDefaultSSOToggle).click();
|
||||
|
||||
cy.get(ssoSelector.passwordEnableToggle).should("be.disabled");
|
||||
|
||||
common.verifyTooltipDisabled(
|
||||
ssoSelector.passwordEnableToggle,
|
||||
"Password login cannot be disabled unless SSO is configured"
|
||||
);
|
||||
|
||||
cy.get(ssoSelector.allowDefaultSSOToggle).click();
|
||||
};
|
||||
|
||||
export const googleSSOPageElements = () => {
|
||||
cy.get(ssoSelector.googleEnableToggle).then(($el) => {
|
||||
if ($el.is(":checked")) {
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
cy.get(ssoSelector.googleEnableToggle).uncheck();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.googleDisableToast
|
||||
);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.disabledLabel
|
||||
);
|
||||
cy.get(ssoSelector.googleEnableToggle).check();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.googleEnabledToast
|
||||
);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
} else {
|
||||
cy.get(ssoSelector.googleEnableToggle).check();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.googleEnabledToast
|
||||
);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
cy.get(ssoSelector.googleEnableToggle).click();
|
||||
cy.get(ssoSelector.saveButton).eq(1).click();
|
||||
|
||||
cy.get(ssoSelector.googleEnableToggle).uncheck();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.googleDisableToast
|
||||
);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.disabledLabel
|
||||
);
|
||||
cy.get(ssoSelector.googleEnableToggle).check();
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
}
|
||||
cy.clearAndType(ssoSelector.clientIdInput, ssoText.testClientId);
|
||||
cy.get(ssoSelector.cancelButton).click();
|
||||
cy.clearAndType(ssoSelector.clientIdInput, ssoText.clientId);
|
||||
cy.get(ssoSelector.saveButton).click();
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.ssoToast2);
|
||||
cy.get(ssoSelector.clientIdInput).should("have.value", ssoText.clientId);
|
||||
});
|
||||
cy.get('[data-cy="modal-title"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"Enable Google"
|
||||
);
|
||||
cy.get('[data-cy="modal-close-button"]').should("be.visible");
|
||||
cy.get('[data-cy="modal-message"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"Enabling Google at the workspace level will override any Google configurations set at the instance level."
|
||||
);
|
||||
cy.get('[data-cy="confirmation-text"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"Are you sure you want to continue?"
|
||||
);
|
||||
cy.get('[data-cy="cancel-button"]')
|
||||
.eq(2)
|
||||
.verifyVisibleElement("have.text", "Cancel");
|
||||
cy.get('[data-cy="enable-button"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"Enable"
|
||||
);
|
||||
|
||||
cy.get('[data-cy="cancel-button"]').eq(2).click();
|
||||
cy.get(ssoSelector.googleEnableToggle).click();
|
||||
cy.get(ssoSelector.saveButton).eq(1).click();
|
||||
cy.get('[data-cy="enable-button"]').click();
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.googleSSOToast);
|
||||
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
cy.get('[data-cy="redirect-url-label"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.redirectUrlLabel
|
||||
);
|
||||
cy.get('[data-cy="redirect-url"]').should("be.visible");
|
||||
cy.get('[data-cy="copy-icon"]').should("be.visible");
|
||||
|
||||
cy.get(ssoSelector.googleEnableToggle).click();
|
||||
cy.get(ssoSelector.saveButton).eq(1).click();
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.googleSSOToast);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.disabledLabel
|
||||
);
|
||||
|
||||
cy.clearAndType(ssoSelector.clientIdInput, ssoText.testClientId);
|
||||
cy.get(ssoSelector.cancelButton).eq(1).click();
|
||||
cy.get(ssoSelector.google).click();
|
||||
cy.get(ssoSelector.clientIdInput).should("have.value", "");
|
||||
cy.get(ssoSelector.googleEnableToggle).click();
|
||||
cy.clearAndType(ssoSelector.clientIdInput, ssoText.clientId);
|
||||
cy.get(ssoSelector.saveButton).eq(1).click();
|
||||
cy.get('[data-cy="enable-button"]').click();
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.googleSSOToast);
|
||||
cy.get(ssoSelector.clientIdInput).should("have.value", ssoText.clientId);
|
||||
};
|
||||
|
||||
export const gitSSOPageElements = () => {
|
||||
cy.get(ssoSelector.gitEnableToggle).then(($el) => {
|
||||
if ($el.is(":checked")) {
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
cy.get(ssoSelector.gitEnableToggle).uncheck();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.gitDisabledToast
|
||||
);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.disabledLabel
|
||||
);
|
||||
cy.get(ssoSelector.gitEnableToggle).check();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.gitEnabledToast
|
||||
);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
} else {
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.disabledLabel
|
||||
);
|
||||
cy.get(ssoSelector.gitEnableToggle).check();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.gitEnabledToast
|
||||
);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
cy.get(ssoSelector.gitEnableToggle).uncheck();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.gitDisabledToast
|
||||
);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.disabledLabel
|
||||
);
|
||||
cy.get(ssoSelector.gitEnableToggle).check();
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
}
|
||||
cy.clearAndType(ssoSelector.hostNameInput, ssoText.hostName);
|
||||
cy.clearAndType(ssoSelector.clientIdInput, ssoText.clientId);
|
||||
cy.clearAndType(ssoSelector.clientSecretInput, ssoText.testClientId);
|
||||
cy.get(ssoSelector.saveButton).click();
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.ssoToast2);
|
||||
cy.get(ssoSelector.hostNameInput).should("have.value", ssoText.hostName);
|
||||
cy.get(ssoSelector.clientIdInput).should("have.value", ssoText.clientId);
|
||||
cy.get(ssoSelector.clientSecretInput).should(
|
||||
"have.value",
|
||||
ssoText.testClientId
|
||||
);
|
||||
});
|
||||
};
|
||||
cy.get(ssoSelector.gitEnableToggle).click();
|
||||
|
||||
export const passwordPageElements = () => {
|
||||
cy.get(ssoSelector.passwordEnableToggle).then(($el) => {
|
||||
if ($el.is(":checked")) {
|
||||
cy.get(ssoSelector.passwordEnableToggle).uncheck();
|
||||
cy.get(commonSelectors.modalComponent).should("be.visible");
|
||||
cy.get(commonSelectors.modalMessage).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.passwordDisableWarning
|
||||
);
|
||||
cy.get(commonSelectors.buttonSelector("Yes")).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.passwordDisabledToast
|
||||
);
|
||||
cy.get(ssoSelector.saveButton).eq(1).click();
|
||||
|
||||
cy.get(ssoSelector.passwordEnableToggle).check();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.passwordEnabledToast
|
||||
);
|
||||
} else {
|
||||
cy.get(ssoSelector.passwordEnableToggle).check();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.passwordEnabledToast
|
||||
);
|
||||
cy.get('[data-cy="modal-title"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"Enable Git"
|
||||
);
|
||||
cy.get('[data-cy="modal-close-button"]').should("be.visible");
|
||||
cy.get('[data-cy="modal-message"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"Enabling Git at the workspace level will override any Git configurations set at the instance level."
|
||||
);
|
||||
cy.get('[data-cy="confirmation-text"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"Are you sure you want to continue?"
|
||||
);
|
||||
cy.get('[data-cy="cancel-button"]')
|
||||
.eq(2)
|
||||
.verifyVisibleElement("have.text", "Cancel");
|
||||
cy.get('[data-cy="enable-button"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"Enable"
|
||||
);
|
||||
|
||||
cy.get(ssoSelector.passwordEnableToggle).uncheck();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.passwordDisabledToast
|
||||
);
|
||||
cy.get('[data-cy="cancel-button"]').eq(2).click();
|
||||
cy.get(ssoSelector.gitEnableToggle).click();
|
||||
cy.get(ssoSelector.saveButton).eq(1).click();
|
||||
cy.get('[data-cy="enable-button"]').click();
|
||||
|
||||
cy.get(ssoSelector.passwordEnableToggle).check();
|
||||
}
|
||||
});
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.gitSSOToast);
|
||||
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
|
||||
cy.get('[data-cy="redirect-url-label"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.redirectUrlLabel
|
||||
);
|
||||
cy.get('[data-cy="redirect-url"]').should("be.visible");
|
||||
cy.get('[data-cy="copy-icon"]').should("be.visible");
|
||||
|
||||
cy.get(ssoSelector.gitEnableToggle).click();
|
||||
cy.get(ssoSelector.saveButton).eq(1).click();
|
||||
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.gitSSOToast);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.disabledLabel
|
||||
);
|
||||
|
||||
cy.get(ssoSelector.gitEnableToggle).click();
|
||||
cy.clearAndType(ssoSelector.hostNameInput, ssoText.hostName);
|
||||
cy.clearAndType(ssoSelector.clientIdInput, ssoText.clientId);
|
||||
cy.clearAndType(ssoSelector.clientSecretInput, ssoText.testClientId);
|
||||
cy.get(ssoSelector.saveButton).eq(1).click();
|
||||
cy.get('[data-cy="enable-button"]').click();
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.gitSSOToast);
|
||||
cy.get(ssoSelector.hostNameInput).should("have.value", ssoText.hostName);
|
||||
cy.get(ssoSelector.clientIdInput).should("have.value", ssoText.clientId);
|
||||
cy.get(ssoSelector.clientSecretInput).should(
|
||||
"have.value",
|
||||
ssoText.testClientId
|
||||
);
|
||||
};
|
||||
|
||||
export const visitWorkspaceLoginPage = () => {
|
||||
cy.get(ssoSelector.generalSettingsElements.generalSettings).click();
|
||||
cy.get(ssoSelector.workspaceLoginUrl).then(($temp) => {
|
||||
const url = $temp.text();
|
||||
common.logout();
|
||||
cy.wait(1000)
|
||||
cy.wait(1000);
|
||||
cy.visit(url);
|
||||
});
|
||||
};
|
||||
|
|
@ -264,7 +247,7 @@ export const workspaceLogin = (workspaceName) => {
|
|||
cy.clearAndType(commonSelectors.workEmailInputField, "dev@tooljet.io");
|
||||
cy.clearAndType(commonSelectors.passwordInputField, "password");
|
||||
cy.get(commonSelectors.loginButton).click();
|
||||
cy.wait(2000)
|
||||
cy.wait(2000);
|
||||
cy.get(commonSelectors.homePageLogo).should("be.visible");
|
||||
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
|
||||
"have.text",
|
||||
|
|
@ -576,3 +559,35 @@ export const updateId = () => {
|
|||
sql: "update sso_configs set id='9628dee2-6fa9-4aca-9c98-ef950601c83e' where sso='git';",
|
||||
});
|
||||
};
|
||||
|
||||
export const setSSOStatus = (workspaceName, ssoType, enabled) => {
|
||||
let workspaceId;
|
||||
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `SELECT id FROM organizations WHERE name = '${workspaceName}'`,
|
||||
}).then((resp) => {
|
||||
workspaceId = resp.rows[0].id;
|
||||
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `SELECT * FROM sso_configs WHERE organization_id = '${workspaceId}' AND sso = '${ssoType}'`,
|
||||
}).then((ssoConfigResp) => {
|
||||
if (ssoConfigResp.rows.length > 0) {
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `UPDATE sso_configs SET enabled = ${enabled ? "true" : "false"
|
||||
} WHERE organization_id = '${workspaceId}' AND sso = '${ssoType}'`,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const defaultSSO = (workspaceName, enabled) => {
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `UPDATE organizations SET inherit_sso = ${enabled ? "true" : "false"
|
||||
} WHERE name = '${workspaceName}'`,
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
2.32.3
|
||||
2.32.5
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useState, useMemo, useContext, useRef, memo, useCallback } from 'react';
|
||||
import React, { useEffect, useState, useMemo, useContext, memo } from 'react';
|
||||
import { Button } from './Components/Button';
|
||||
import { Image } from './Components/Image';
|
||||
import { Text } from './Components/Text';
|
||||
|
|
@ -42,7 +42,6 @@ import { Html } from './Components/Html';
|
|||
import { ButtonGroup } from './Components/ButtonGroup';
|
||||
import { CustomComponent } from './Components/CustomComponent/CustomComponent';
|
||||
import { VerticalDivider } from './Components/verticalDivider';
|
||||
import { PDF } from './Components/PDF';
|
||||
import { ColorPicker } from './Components/ColorPicker';
|
||||
import { KanbanBoard } from './Components/KanbanBoard/KanbanBoard';
|
||||
import { Kanban } from './Components/Kanban/Kanban';
|
||||
|
|
@ -68,6 +67,7 @@ import { EditorContext } from '@/Editor/Context/EditorContextWrapper';
|
|||
import { useTranslation } from 'react-i18next';
|
||||
import { useCurrentState } from '@/_stores/currentStateStore';
|
||||
import { useAppInfo } from '@/_stores/appDataStore';
|
||||
import { isPDFSupported } from '@/_stores/utils';
|
||||
|
||||
export const AllComponents = {
|
||||
Button,
|
||||
|
|
@ -112,7 +112,6 @@ export const AllComponents = {
|
|||
ButtonGroup,
|
||||
CustomComponent,
|
||||
VerticalDivider,
|
||||
PDF,
|
||||
ColorPicker,
|
||||
KanbanBoard,
|
||||
Kanban,
|
||||
|
|
@ -124,6 +123,14 @@ export const AllComponents = {
|
|||
BoundedBox,
|
||||
};
|
||||
|
||||
/**
|
||||
* Conditionally importing PDF component since importing it breaks app in older versions of browsers.
|
||||
* refer: https://github.com/wojtekmaj/react-pdf?tab=readme-ov-file#compatibility
|
||||
**/
|
||||
if (isPDFSupported()) {
|
||||
AllComponents.PDF = await import('./Components/PDF').then((module) => module.PDF);
|
||||
}
|
||||
|
||||
export const Box = memo(
|
||||
({
|
||||
id,
|
||||
|
|
@ -281,6 +288,9 @@ export const Box = memo(
|
|||
...{ validationObject: component.definition.validation, currentState },
|
||||
customResolveObjects: customResolvables,
|
||||
});
|
||||
|
||||
const shouldHideWidget = component.component === 'PDF' && !isPDFSupported();
|
||||
|
||||
return (
|
||||
<OverlayTrigger
|
||||
placement={inCanvas ? 'auto' : 'top'}
|
||||
|
|
@ -315,7 +325,7 @@ export const Box = memo(
|
|||
}}
|
||||
role={preview ? 'BoxPreview' : 'Box'}
|
||||
>
|
||||
{!resetComponent ? (
|
||||
{!resetComponent && !shouldHideWidget ? (
|
||||
<ComponentToRender
|
||||
onComponentClick={onComponentClick}
|
||||
onComponentOptionChanged={onComponentOptionChanged}
|
||||
|
|
|
|||
|
|
@ -444,15 +444,37 @@ export function Table({
|
|||
}));
|
||||
|
||||
tableData = useMemo(() => {
|
||||
return tableData.map((row) => ({
|
||||
...row,
|
||||
...Object.fromEntries(
|
||||
transformations.map((t) => [
|
||||
t.key,
|
||||
resolveReferences(t.transformation, currentState, row[t.key], { cellValue: row[t.key], rowData: row }),
|
||||
])
|
||||
),
|
||||
}));
|
||||
return tableData.map((row) => {
|
||||
return {
|
||||
...row,
|
||||
...Object.fromEntries(
|
||||
transformations.map(({ key, transformation }) => {
|
||||
const nestedKeys = key.includes('.') && key.split('.');
|
||||
if (nestedKeys) {
|
||||
// Single-level nested property
|
||||
const [nestedKey, subKey] = nestedKeys;
|
||||
const nestedObject = row[nestedKey];
|
||||
return [
|
||||
nestedKey,
|
||||
{
|
||||
...nestedObject,
|
||||
[subKey]: resolveReferences(transformation, currentState, row[key], {
|
||||
cellValue: row?.[nestedKey]?.[subKey],
|
||||
rowData: row,
|
||||
}),
|
||||
},
|
||||
];
|
||||
} else {
|
||||
// Non-nested property
|
||||
return [
|
||||
key,
|
||||
resolveReferences(transformation, currentState, row[key], { cellValue: row[key], rowData: row }),
|
||||
];
|
||||
}
|
||||
})
|
||||
),
|
||||
};
|
||||
});
|
||||
}, [JSON.stringify([transformations, currentState, component.definition.properties.data.value])]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import { shallow } from 'zustand/shallow';
|
|||
import _ from 'lodash';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { diff } from 'deep-object-diff';
|
||||
import { isPDFSupported } from '@/_stores/utils';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
const NO_OF_GRIDS = 43;
|
||||
|
||||
|
|
@ -256,6 +258,13 @@ export const Container = ({
|
|||
return;
|
||||
}
|
||||
|
||||
if (item.component.component === 'PDF' && !isPDFSupported()) {
|
||||
toast.error(
|
||||
'PDF is not supported in this version of browser. We recommend upgrading to the latest version for full support.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.name === 'comment') {
|
||||
const canvasBoundingRect = document.getElementsByClassName('real-canvas')[0].getBoundingClientRect();
|
||||
const offsetFromTopOfWindow = canvasBoundingRect.top;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import { useMounted } from '@/_hooks/use-mount';
|
|||
import { useEditorStore } from '@/_stores/editorStore';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { diff } from 'deep-object-diff';
|
||||
import { isPDFSupported } from '@/_stores/utils';
|
||||
|
||||
const NO_OF_GRIDS = 43;
|
||||
|
||||
|
|
@ -308,6 +309,13 @@ export const SubContainer = ({
|
|||
() => ({
|
||||
accept: ItemTypes.BOX,
|
||||
drop(item, monitor) {
|
||||
if (item.component.component === 'PDF' && !isPDFSupported()) {
|
||||
toast.error(
|
||||
'PDF is not supported in this version of browser. We recommend upgrading to the latest version for full support.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const componentMeta = _.cloneDeep(
|
||||
componentTypes.find((component) => component.component === item.component.component)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -15,8 +15,10 @@ function DisablePasswordLoginModal({ show, disablePasswordLogin, setShowModal, r
|
|||
|
||||
const modalContent = (
|
||||
<div>
|
||||
<p>Disable password login only if you have configured SSO or else you will get locked out.</p>
|
||||
<p>Are you sure you want to continue?</p>
|
||||
<p data-cy="modal-message">
|
||||
Disable password login only if you have configured SSO or else you will get locked out.
|
||||
</p>
|
||||
<p data-cy="confrmation-text">Are you sure you want to continue?</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
|
@ -25,7 +27,7 @@ function DisablePasswordLoginModal({ show, disablePasswordLogin, setShowModal, r
|
|||
<ButtonSolid variant="tertiary" onClick={handleClose} data-cy="cancel-button">
|
||||
Cancel
|
||||
</ButtonSolid>
|
||||
<ButtonSolid variant={'dangerPrimary'} onClick={handleDisable}>
|
||||
<ButtonSolid variant={'dangerPrimary'} onClick={handleDisable} data-cy="confirmation-button">
|
||||
Disable
|
||||
</ButtonSolid>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -134,8 +134,8 @@ export function GithubSSOModal({ settings, onClose, onUpdateSSOSettings, isInsta
|
|||
}}
|
||||
>
|
||||
<div>
|
||||
<label className="switch">
|
||||
<input type="checkbox" checked={enabled} onChange={onToggleChange} data-cy="github-toggle-input" />
|
||||
<label className="switch" data-cy="github-toggle-input">
|
||||
<input type="checkbox" checked={enabled} onChange={onToggleChange} />
|
||||
<span className="slider round"></span>
|
||||
</label>
|
||||
<span className="sso-type-header" data-cy="card-title" style={{ marginBottom: '0px', fontWeight: '500' }}>
|
||||
|
|
|
|||
|
|
@ -104,8 +104,8 @@ export function GoogleSSOModal({ settings, onClose, onUpdateSSOSettings, isInsta
|
|||
}}
|
||||
>
|
||||
<div>
|
||||
<label className="switch">
|
||||
<input type="checkbox" checked={enabled} onChange={onToggleChange} data-cy="google-enable-toggle" />
|
||||
<label className="switch" data-cy="google-enable-toggle">
|
||||
<input type="checkbox" checked={enabled} onChange={onToggleChange} />
|
||||
<span className="slider round"></span>
|
||||
</label>
|
||||
<span className="sso-type-header" data-cy="card-title" style={{ marginBottom: '0px', fontWeight: '500' }}>
|
||||
|
|
|
|||
|
|
@ -241,7 +241,12 @@ class SSOConfiguration extends React.Component {
|
|||
const isEnabled = this.state[isEnabledKey];
|
||||
|
||||
return (
|
||||
<div className="sso-option" key={key} onClick={() => this.openModal(key)} data-cy="sso-card">
|
||||
<div
|
||||
className="sso-option"
|
||||
key={key}
|
||||
onClick={() => this.openModal(key)}
|
||||
data-cy={`${name.toLowerCase().replace(/\s+/g, '-')}-sso-card`}
|
||||
>
|
||||
<div className="sso-option-label">
|
||||
{
|
||||
<div
|
||||
|
|
@ -303,7 +308,7 @@ class SSOConfiguration extends React.Component {
|
|||
justifyContent: 'flex-start',
|
||||
}}
|
||||
bsPrefix="no-caret-dropdown-toggle"
|
||||
data-testid="instance-sso-toggle"
|
||||
data-cy="dropdown-custom-toggle"
|
||||
>
|
||||
<div
|
||||
className="sso-option-label"
|
||||
|
|
@ -346,7 +351,7 @@ class SSOConfiguration extends React.Component {
|
|||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
|
||||
<label className="switch" style={{ marginLeft: '95px' }}>
|
||||
<label className="switch" style={{ marginLeft: '95px' }} data-cy="instance-sso-toggle">
|
||||
<input type="checkbox" checked={defaultSSO} onChange={this.toggleDefaultSSO} />
|
||||
<span className="slider round"></span>
|
||||
</label>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ export function handleResponse(response, avoidRedirection = false) {
|
|||
const data = text && JSON.parse(text);
|
||||
if (!response.ok) {
|
||||
if ([401].indexOf(response.status) !== -1) {
|
||||
avoidRedirection ? authenticationService.logout() : location.reload(true);
|
||||
const errorMessageJson = typeof data.message === 'string' ? JSON.parse(data.message) : undefined;
|
||||
const workspaceId = errorMessageJson?.organizationId;
|
||||
avoidRedirection ? authenticationService.logout(false, workspaceId) : location.reload(true);
|
||||
}
|
||||
|
||||
const error = (data && data.message) || response.statusText;
|
||||
|
|
|
|||
|
|
@ -294,16 +294,16 @@ function resetPassword(params) {
|
|||
return fetch(`${config.apiUrl}/reset-password`, requestOptions).then(handleResponse);
|
||||
}
|
||||
|
||||
function logout(avoidRedirection = false) {
|
||||
function logout(avoidRedirection = false, organizationId = null) {
|
||||
const requestOptions = {
|
||||
method: 'GET',
|
||||
headers: authHeader(),
|
||||
credentials: 'include',
|
||||
};
|
||||
const workspaceId = getWorkspaceId() || organizationId;
|
||||
|
||||
const redirectToLoginPage = () => {
|
||||
const loginPath =
|
||||
(window.public_config?.SUB_PATH || '/') + 'login' + `${getWorkspaceId() ? `/${getWorkspaceId()}` : ''}`;
|
||||
const loginPath = (window.public_config?.SUB_PATH || '/') + 'login' + `${workspaceId ? `/${workspaceId}` : ''}`;
|
||||
if (avoidRedirection) {
|
||||
window.location.href = loginPath;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ function getUsersNotInGroup(searchInput, groupPermissionId) {
|
|||
credentials: 'include',
|
||||
};
|
||||
return fetch(
|
||||
`${config.apiUrl}/group_permissions/${groupPermissionId}/addable_users?input=${searchInput}`,
|
||||
`${config.apiUrl}/group_permissions/${groupPermissionId}/addable_users?input=${searchInput.trim()}`,
|
||||
requestOptions
|
||||
).then(handleResponse);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -329,3 +329,68 @@ function toRemoveExposedvariablesFromComponentDiff(object) {
|
|||
|
||||
return copy;
|
||||
}
|
||||
|
||||
export function isPDFSupported() {
|
||||
const browser = getBrowserUserAgent();
|
||||
|
||||
if (!browser) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const isChrome = browser.name === 'Chrome' && browser.major >= 92;
|
||||
const isEdge = browser.name === 'Edge' && browser.major >= 92;
|
||||
const isSafari = browser.name === 'Safari' && browser.major >= 15 && browser.minor >= 4; // Handle minor version check for Safari
|
||||
const isFirefox = browser.name === 'Firefox' && browser.major >= 90;
|
||||
|
||||
console.log('browser--', browser, isChrome || isEdge || isSafari || isFirefox);
|
||||
|
||||
return isChrome || isEdge || isSafari || isFirefox;
|
||||
}
|
||||
|
||||
export function getBrowserUserAgent(userAgent) {
|
||||
var regexps = {
|
||||
Chrome: [/Chrome\/(\S+)/],
|
||||
Firefox: [/Firefox\/(\S+)/],
|
||||
MSIE: [/MSIE (\S+);/],
|
||||
Opera: [/Opera\/.*?Version\/(\S+)/ /* Opera 10 */, /Opera\/(\S+)/ /* Opera 9 and older */],
|
||||
Safari: [/Version\/(\S+).*?Safari\//],
|
||||
},
|
||||
re,
|
||||
m,
|
||||
browser,
|
||||
version;
|
||||
|
||||
if (userAgent === undefined) userAgent = navigator.userAgent;
|
||||
|
||||
for (browser in regexps)
|
||||
while ((re = regexps[browser].shift()))
|
||||
if ((m = userAgent.match(re))) {
|
||||
version = m[1].match(new RegExp('[^.]+(?:.[^.]+){0,1}'))[0];
|
||||
const { major, minor } = extractVersion(version);
|
||||
return {
|
||||
name: browser,
|
||||
major,
|
||||
minor,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function extractVersion(versionStr) {
|
||||
// Split the string by "."
|
||||
const parts = versionStr.split('.');
|
||||
|
||||
// Check for valid input
|
||||
if (parts.length === 0 || parts.some((part) => isNaN(part))) {
|
||||
return { major: null, minor: null };
|
||||
}
|
||||
|
||||
// Extract major version
|
||||
const major = parseInt(parts[0], 10);
|
||||
|
||||
// Handle minor version (default to 0)
|
||||
const minor = parts.length > 1 ? parseInt(parts[1], 10) : 0;
|
||||
|
||||
return { major, minor };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
2.32.3
|
||||
2.32.5
|
||||
|
|
|
|||
|
|
@ -110,8 +110,8 @@ export class GroupPermissionsController {
|
|||
@UseGuards(JwtAuthGuard, PoliciesGuard)
|
||||
@CheckPolicies((ability: AppAbility) => ability.can('accessGroupPermission', UserEntity))
|
||||
@Get(':id/addable_users')
|
||||
async addableUsers(@User() user, @Param('id') id, @Query('input') searchInput) {
|
||||
const users = await this.groupPermissionsService.findAddableUsers(user, id, searchInput);
|
||||
async addableUsers(@User() user, @Param('id') id, @Query('input') searchInput: string) {
|
||||
const users = await this.groupPermissionsService.findAddableUsers(user, id, searchInput.trim());
|
||||
|
||||
return decamelizeKeys({ users });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ExecutionContext, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { ExecutionContext, Injectable, NotFoundException, UnauthorizedException } from '@nestjs/common';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { AppsService } from 'src/services/apps.service';
|
||||
|
||||
|
|
@ -25,6 +25,17 @@ export class AppAuthGuard extends AuthGuard('jwt') {
|
|||
return true;
|
||||
}
|
||||
|
||||
return super.canActivate(context);
|
||||
// Throw a custom exception with workspace ID if the app is not public
|
||||
try {
|
||||
const authResult = await super.canActivate(context);
|
||||
return authResult;
|
||||
} catch (error) {
|
||||
throw new UnauthorizedException(
|
||||
JSON.stringify({
|
||||
organizationId: app?.organizationId,
|
||||
message: 'Authentication is required to access this app.',
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -470,15 +470,17 @@ export class GroupPermissionsService {
|
|||
|
||||
const getOrConditions = () => {
|
||||
return new Brackets((qb) => {
|
||||
qb.orWhere('lower(user.email) like :email', {
|
||||
email: `%${searchInput.toLowerCase()}%`,
|
||||
});
|
||||
qb.orWhere('lower(user.firstName) like :firstName', {
|
||||
firstName: `%${searchInput.toLowerCase()}%`,
|
||||
});
|
||||
qb.orWhere('lower(user.lastName) like :lastName', {
|
||||
lastName: `%${searchInput.toLowerCase()}%`,
|
||||
});
|
||||
if (searchInput) {
|
||||
qb.orWhere('lower(user.email) like :email', {
|
||||
email: `%${searchInput.toLowerCase()}%`,
|
||||
});
|
||||
qb.orWhere('lower(user.firstName) like :firstName', {
|
||||
firstName: `%${searchInput.toLowerCase()}%`,
|
||||
});
|
||||
qb.orWhere('lower(user.lastName) like :lastName', {
|
||||
lastName: `%${searchInput.toLowerCase()}%`,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -490,14 +492,13 @@ export class GroupPermissionsService {
|
|||
'organization_users.organizationId = :organizationId',
|
||||
{ organizationId: user.organizationId }
|
||||
)
|
||||
.andWhere(getOrConditions)
|
||||
.where('user.id NOT IN (:...userList)', { userList: [...usersInGroupIds, ...adminUserIds] });
|
||||
.where('user.id NOT IN (:...userList)', { userList: [...usersInGroupIds, ...adminUserIds] })
|
||||
.andWhere(getOrConditions());
|
||||
|
||||
if (searchInput) {
|
||||
builtQuery.andWhere(getOrConditions);
|
||||
} else {
|
||||
if (!searchInput) {
|
||||
builtQuery.take(10); // Limiting to 10 users if there's no search input
|
||||
}
|
||||
|
||||
builtQuery.orderBy('user.firstName');
|
||||
return await builtQuery.getMany();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue