From e03d0a1716910fd70be500d480f8d5691bee02d7 Mon Sep 17 00:00:00 2001 From: gsmithun4 Date: Wed, 13 Mar 2024 13:04:24 +0530 Subject: [PATCH 1/7] bump version --- .version | 2 +- frontend/.version | 2 +- server/.version | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.version b/.version index 5506598e0f..fb3a067795 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.32.3 +2.32.4 diff --git a/frontend/.version b/frontend/.version index 5506598e0f..fb3a067795 100644 --- a/frontend/.version +++ b/frontend/.version @@ -1 +1 @@ -2.32.3 +2.32.4 diff --git a/server/.version b/server/.version index 5506598e0f..fb3a067795 100644 --- a/server/.version +++ b/server/.version @@ -1 +1 @@ -2.32.3 +2.32.4 From c8c03d70509c82bf68f50997748d94ef0580e11b Mon Sep 17 00:00:00 2001 From: Anantshree Chandola Date: Wed, 13 Mar 2024 13:05:44 +0530 Subject: [PATCH 2/7] Corrected app redirection flow to workspace login (#8995) --- frontend/src/_helpers/handle-response.js | 4 +++- frontend/src/_services/authentication.service.js | 6 +++--- server/src/modules/auth/app-auth.guard.ts | 15 +++++++++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/frontend/src/_helpers/handle-response.js b/frontend/src/_helpers/handle-response.js index 7d9879ced0..708cd0ccd1 100644 --- a/frontend/src/_helpers/handle-response.js +++ b/frontend/src/_helpers/handle-response.js @@ -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; diff --git a/frontend/src/_services/authentication.service.js b/frontend/src/_services/authentication.service.js index e19b86975d..58d5d02f4a 100644 --- a/frontend/src/_services/authentication.service.js +++ b/frontend/src/_services/authentication.service.js @@ -249,16 +249,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 { diff --git a/server/src/modules/auth/app-auth.guard.ts b/server/src/modules/auth/app-auth.guard.ts index de4f5b390d..38200039cc 100644 --- a/server/src/modules/auth/app-auth.guard.ts +++ b/server/src/modules/auth/app-auth.guard.ts @@ -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.', + }) + ); + } } } From aecd7b81a12212368b708a00a2cec8f17812ad0d Mon Sep 17 00:00:00 2001 From: kriks7iitk <34170719+kriks7iitk@users.noreply.github.com> Date: Wed, 13 Mar 2024 13:06:31 +0530 Subject: [PATCH 3/7] Fix user group permission (#9069) * fixed user search * fixed trim for search input for user search in group permission * Modify cypress config --------- Co-authored-by: Kritagya Co-authored-by: Ajith KV --- cypress-tests/cypress-app-builder.config.js | 4 +-- cypress-tests/cypress-marketplace.config.js | 4 +-- cypress-tests/cypress-workspace.config.js | 4 +-- .../src/_services/groupPermission.service.js | 2 +- .../group_permissions.controller.ts | 4 +-- .../src/services/group_permissions.service.ts | 29 ++++++++++--------- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/cypress-tests/cypress-app-builder.config.js b/cypress-tests/cypress-app-builder.config.js index 756ef58abe..5d291f59c1 100644 --- a/cypress-tests/cypress-app-builder.config.js +++ b/cypress-tests/cypress-app-builder.config.js @@ -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, diff --git a/cypress-tests/cypress-marketplace.config.js b/cypress-tests/cypress-marketplace.config.js index f5e8661b1d..967e938248 100644 --- a/cypress-tests/cypress-marketplace.config.js +++ b/cypress-tests/cypress-marketplace.config.js @@ -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, diff --git a/cypress-tests/cypress-workspace.config.js b/cypress-tests/cypress-workspace.config.js index 0508e9910f..e22e022a9a 100644 --- a/cypress-tests/cypress-workspace.config.js +++ b/cypress-tests/cypress-workspace.config.js @@ -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, diff --git a/frontend/src/_services/groupPermission.service.js b/frontend/src/_services/groupPermission.service.js index 54b3fc5110..14e7eeb2b9 100644 --- a/frontend/src/_services/groupPermission.service.js +++ b/frontend/src/_services/groupPermission.service.js @@ -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); } diff --git a/server/src/controllers/group_permissions.controller.ts b/server/src/controllers/group_permissions.controller.ts index f96bca9022..f9ad29ef15 100644 --- a/server/src/controllers/group_permissions.controller.ts +++ b/server/src/controllers/group_permissions.controller.ts @@ -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 }); } diff --git a/server/src/services/group_permissions.service.ts b/server/src/services/group_permissions.service.ts index 9e6b8105bf..7a7412afc5 100644 --- a/server/src/services/group_permissions.service.ts +++ b/server/src/services/group_permissions.service.ts @@ -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(); } From 5817da33f97a675e99357c4c7adc3bb259fea98f Mon Sep 17 00:00:00 2001 From: Manish Kushare <37823141+manishkushare@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:47:51 +0530 Subject: [PATCH 4/7] hotfix : Transformation getting applied correctly for nested column (#9047) * fix: make visibility none only when its set to false * add visibility only for components which have visibility in styles * making logic for visibility central * transformation not working for nested column * remove unwanted changes --------- Co-authored-by: stepinfwd --- .../src/Editor/Components/Table/Table.jsx | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/frontend/src/Editor/Components/Table/Table.jsx b/frontend/src/Editor/Components/Table/Table.jsx index c1e740097a..00ef459a82 100644 --- a/frontend/src/Editor/Components/Table/Table.jsx +++ b/frontend/src/Editor/Components/Table/Table.jsx @@ -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(() => { From 51f44074bbb2b096afbc5baf586d5c3b2e09d494 Mon Sep 17 00:00:00 2001 From: Johnson Cherian Date: Wed, 13 Mar 2024 16:54:24 +0530 Subject: [PATCH 5/7] fix: import pdf component conditionally in supported browsers (#9071) * fix: render pdf component conditionally in supported browsers * refactor: added additonal comments * feat: conditional render of widget in view page * refactor: removed unused packages * refactor: removed unused packages * refactor: removed unused code * refactor: remove dead code * refactor: minor formatting * refactor: minor formatting * feat: hide pdf in edit as well for older browsers * chore: minor release version bump --- .version | 2 +- frontend/.version | 2 +- frontend/src/Editor/Box.jsx | 18 ++++++-- frontend/src/Editor/Container.jsx | 9 ++++ frontend/src/Editor/SubContainer.jsx | 8 ++++ frontend/src/_stores/utils.js | 65 ++++++++++++++++++++++++++++ server/.version | 2 +- 7 files changed, 99 insertions(+), 7 deletions(-) diff --git a/.version b/.version index 5506598e0f..fb3a067795 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.32.3 +2.32.4 diff --git a/frontend/.version b/frontend/.version index 5506598e0f..fb3a067795 100644 --- a/frontend/.version +++ b/frontend/.version @@ -1 +1 @@ -2.32.3 +2.32.4 diff --git a/frontend/src/Editor/Box.jsx b/frontend/src/Editor/Box.jsx index 21a45089c3..bb11eb38d6 100644 --- a/frontend/src/Editor/Box.jsx +++ b/frontend/src/Editor/Box.jsx @@ -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 ( - {!resetComponent ? ( + {!resetComponent && !shouldHideWidget ? ( ({ 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) ); diff --git a/frontend/src/_stores/utils.js b/frontend/src/_stores/utils.js index 76069b1e65..0a6ec6d10f 100644 --- a/frontend/src/_stores/utils.js +++ b/frontend/src/_stores/utils.js @@ -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 }; +} diff --git a/server/.version b/server/.version index 5506598e0f..fb3a067795 100644 --- a/server/.version +++ b/server/.version @@ -1 +1 @@ -2.32.3 +2.32.4 From 2dfb2aeb0193efb85c0c40257fb7e119980f829e Mon Sep 17 00:00:00 2001 From: Ajith KV Date: Wed, 13 Mar 2024 17:35:36 +0530 Subject: [PATCH 6/7] Modified SSO cypress test cases (#9077) * Modify SSO cypress test cases * modify data-cy * Update path --- .../cypress/constants/selectors/common.js | 3 +- .../cypress/constants/selectors/manageSSO.js | 21 +- .../cypress/constants/texts/manageSSO.js | 30 +- .../authentication/forgotPassword.cy.js | 4 +- .../commonTestcases/workspace/manageSSO.cy.js | 74 ++-- .../workspace/manageUsers.cy.js | 2 +- cypress-tests/cypress/support/utils/common.js | 8 + .../cypress/support/utils/manageSSO.js | 385 +++++++++--------- .../DisablePasswordLoginModal.jsx | 8 +- .../OrganizationLogin/GithubSsoModal.jsx | 4 +- .../OrganizationLogin/GoogleSsoModal.jsx | 4 +- .../OrganizationLogin/SsoConfiguration.jsx | 11 +- 12 files changed, 294 insertions(+), 260 deletions(-) diff --git a/cypress-tests/cypress/constants/selectors/common.js b/cypress-tests/cypress/constants/selectors/common.js index 6aab19607c..7243adb353 100644 --- a/cypress-tests/cypress/constants/selectors/common.js +++ b/cypress-tests/cypress/constants/selectors/common.js @@ -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 = { diff --git a/cypress-tests/cypress/constants/selectors/manageSSO.js b/cypress-tests/cypress/constants/selectors/manageSSO.js index 2c0b0e5d0e..6ec26231b1 100644 --- a/cypress-tests/cypress/constants/selectors/manageSSO.js +++ b/cypress-tests/cypress/constants/selectors/manageSSO.js @@ -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"]', }; diff --git a/cypress-tests/cypress/constants/texts/manageSSO.js b/cypress-tests/cypress/constants/texts/manageSSO.js index 7736de3728..c1a95e7179 100644 --- a/cypress-tests/cypress/constants/texts/manageSSO.js +++ b/cypress-tests/cypress/constants/texts/manageSSO.js @@ -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", }; diff --git a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/authentication/forgotPassword.cy.js b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/authentication/forgotPassword.cy.js index d6e6a7e8f2..dda3cd887c 100644 --- a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/authentication/forgotPassword.cy.js +++ b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/authentication/forgotPassword.cy.js @@ -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"; diff --git a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageSSO.cy.js b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageSSO.cy.js index 48c40fde84..d91a207630 100644 --- a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageSSO.cy.js +++ b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageSSO.cy.js @@ -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); diff --git a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageUsers.cy.js b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageUsers.cy.js index 899fbb4bb2..e41aeee42b 100644 --- a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageUsers.cy.js +++ b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageUsers.cy.js @@ -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]", ""); diff --git a/cypress-tests/cypress/support/utils/common.js b/cypress-tests/cypress/support/utils/common.js index 3dc04c68ec..c4c1b602bd 100644 --- a/cypress-tests/cypress/support/utils/common.js +++ b/cypress-tests/cypress/support/utils/common.js @@ -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); + }); +}; \ No newline at end of file diff --git a/cypress-tests/cypress/support/utils/manageSSO.js b/cypress-tests/cypress/support/utils/manageSSO.js index 7c9a724888..119bd15d6a 100644 --- a/cypress-tests/cypress/support/utils/manageSSO.js +++ b/cypress-tests/cypress/support/utils/manageSSO.js @@ -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}'`, + }); +}; diff --git a/frontend/src/_components/OrganizationLogin/DisablePasswordLoginModal.jsx b/frontend/src/_components/OrganizationLogin/DisablePasswordLoginModal.jsx index c6385ba9ec..a9f4e4c3e9 100644 --- a/frontend/src/_components/OrganizationLogin/DisablePasswordLoginModal.jsx +++ b/frontend/src/_components/OrganizationLogin/DisablePasswordLoginModal.jsx @@ -15,8 +15,10 @@ function DisablePasswordLoginModal({ show, disablePasswordLogin, setShowModal, r const modalContent = (
-

Disable password login only if you have configured SSO or else you will get locked out.

-

Are you sure you want to continue?

+

+ Disable password login only if you have configured SSO or else you will get locked out. +

+

Are you sure you want to continue?

); @@ -25,7 +27,7 @@ function DisablePasswordLoginModal({ show, disablePasswordLogin, setShowModal, r Cancel - + Disable diff --git a/frontend/src/_components/OrganizationLogin/GithubSsoModal.jsx b/frontend/src/_components/OrganizationLogin/GithubSsoModal.jsx index a2ee10b9bd..425020f00a 100644 --- a/frontend/src/_components/OrganizationLogin/GithubSsoModal.jsx +++ b/frontend/src/_components/OrganizationLogin/GithubSsoModal.jsx @@ -134,8 +134,8 @@ export function GithubSSOModal({ settings, onClose, onUpdateSSOSettings, isInsta }} >
-