diff --git a/.github/workflows/tooljet-release-docker-image-build.yml b/.github/workflows/tooljet-release-docker-image-build.yml index 2bd0eaf41a..780c067c53 100644 --- a/.github/workflows/tooljet-release-docker-image-build.yml +++ b/.github/workflows/tooljet-release-docker-image-build.yml @@ -115,7 +115,7 @@ jobs: - name: Send Slack Notification run: | if [[ "${{ job.status }}" == "success" ]]; then - message="Job '${{ env.JOB_NAME }}' succeeded! tooljet/tooljet-ce:${{ github.event.inputs.image }}" + message="ToolJet community image published:\n\`tooljet/tooljet-ce:${{ github.event.inputs.image }}\`" else message="Job '${{ env.JOB_NAME }}' failed! tooljet/tooljet-ce:${{ github.event.inputs.image }}" fi diff --git a/.version b/.version index ea5b93e744..544fe5d438 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.30.4 +2.32.2 diff --git a/cypress-tests/cypress/commands/commands.js b/cypress-tests/cypress/commands/commands.js index 054d601bbe..72914c8fa6 100644 --- a/cypress-tests/cypress/commands/commands.js +++ b/cypress-tests/cypress/commands/commands.js @@ -115,9 +115,9 @@ Cypress.Commands.add( .last() .click() .type(createBackspaceText(text), { delay: 0 }), - { - delay: 0, - }; + { + delay: 0, + }; }); if (!Array.isArray(value)) { cy.wrap(subject).last().type(value, { @@ -193,9 +193,9 @@ Cypress.Commands.add( .invoke("text") .then((text) => { cy.wrap(subject).realType(createBackspaceText(text)), - { - delay: 0, - }; + { + delay: 0, + }; }); } ); @@ -273,7 +273,7 @@ Cypress.Commands.add("waitForAppLoad", () => { const API_ENDPOINT = Cypress.env("environment") === "Community" ? "/api/v2/data_sources" - : "/api/app-environments/**"; + : "/api/app-environments**"; const TIMEOUT = 15000; @@ -460,3 +460,11 @@ Cypress.Commands.add("skipWalkthrough", () => { win.localStorage.setItem("walkthroughCompleted", "true"); }); }); + +Cypress.Commands.add("appPrivacy", (appName, isPublic) => { + const isPublicValue = isPublic ? "true" : "false"; + cy.task("updateId", { + dbconfig: Cypress.env("app_db"), + sql: `UPDATE apps SET is_public = ${isPublicValue} WHERE name = '${appName}';`, + }); +}); diff --git a/cypress-tests/cypress/e2e/ce/workspaceConstants.cy.js b/cypress-tests/cypress/e2e/ce/workspaceConstants.cy.js index cf76eb1a3f..1fc8cab168 100644 --- a/cypress-tests/cypress/e2e/ce/workspaceConstants.cy.js +++ b/cypress-tests/cypress/e2e/ce/workspaceConstants.cy.js @@ -10,7 +10,6 @@ import { } from "Support/utils/workspaceConstants"; import { buttonText } from "Texts/button"; import { - verifyAndModifyParameter, editAndVerifyWidgetName, } from "Support/utils/commonWidget"; import { verifypreview } from "Support/utils/dataSource"; @@ -276,10 +275,12 @@ describe("Workspace constants", () => { verifypreview("raw", "dJ_8Q~BcaMPd"); cy.dragAndDropWidget("Text", 550, 350); - editAndVerifyWidgetName(data.constantsName); + editAndVerifyWidgetName(data.constantsName, []); cy.waitForAutoSave(); - verifyAndModifyParameter("Text", `{{constants.${data.constantsName}`); + cy.get( + '[data-cy="textcomponenttextinput-input-field"]' + ).clearAndTypeOnCodeMirror(`{{constants.${data.constantsName}`); cy.forceClickOnCanvas(); cy.waitForAutoSave(); diff --git a/cypress-tests/cypress/e2e/editor/globalSetingsHappyPath.cy.js b/cypress-tests/cypress/e2e/editor/globalSetingsHappyPath.cy.js index d1fe99ce82..195262cfdc 100644 --- a/cypress-tests/cypress/e2e/editor/globalSetingsHappyPath.cy.js +++ b/cypress-tests/cypress/e2e/editor/globalSetingsHappyPath.cy.js @@ -95,16 +95,15 @@ describe("Editor- Global Settings", () => { cy.forceClickOnCanvas(); cy.wait(500); cy.waitForAutoSave(); - - cy.get('[data-cy="button-release"]').click(); - cy.get('[data-cy="yes-button"]').click(); - cy.get('[data-cy="editor-page-logo"]').click(); - cy.get('[data-cy="back-to-app-option"]').click(); - cy.get(`[data-cy="${data.appName.toLowerCase()}-card"]`) - .realHover() - .find('[data-cy="launch-button"]') - .invoke("attr", "class") - .should("contains", "disabled-btn"); + //Fix this after the release. 2.9.0 + // cy.get('[data-cy="button-release"]').click(); + // cy.get('[data-cy="yes-button"]').click(); + // cy.get('[data-cy="editor-page-logo"]').click(); + // cy.get(`[data-cy="${data.appName.toLowerCase()}-card"]`) + // .realHover() + // .find('[data-cy="launch-button"]') + // .invoke("attr", "class") + // .should("contains", "disabled-btn"); cy.apiDeleteApp(); }); diff --git a/cypress-tests/cypress/e2e/editor/queries/chainingOfQueries.cy.js b/cypress-tests/cypress/e2e/editor/queries/chainingOfQueries.cy.js index ad6dfe43fa..87386554c1 100644 --- a/cypress-tests/cypress/e2e/editor/queries/chainingOfQueries.cy.js +++ b/cypress-tests/cypress/e2e/editor/queries/chainingOfQueries.cy.js @@ -100,7 +100,7 @@ describe("Chaining of queries", () => { .find("input") .type(`{selectAll}{backspace}psql{enter}`); cy.forceClickOnCanvas(); - + cy.wait(2500) cy.get(commonWidgetSelector.draggableWidget("button1")).click(); cy.verifyToastMessage(commonSelectors.toastMessage, "psql"); cy.verifyToastMessage(commonSelectors.toastMessage, "runjs"); @@ -140,7 +140,7 @@ describe("Chaining of queries", () => { .find("input") .type(`{selectAll}{backspace}runjs{enter}`); cy.forceClickOnCanvas(); - + cy.wait(2500) cy.get(commonWidgetSelector.draggableWidget("button1")).click(); cy.verifyToastMessage(commonSelectors.toastMessage, "runjs"); cy.verifyToastMessage(commonSelectors.toastMessage, "runpy"); diff --git a/cypress-tests/cypress/e2e/editor/widget/buttonHappyPath.cy.js b/cypress-tests/cypress/e2e/editor/widget/buttonHappyPath.cy.js index 5213974aa9..67be49e530 100644 --- a/cypress-tests/cypress/e2e/editor/widget/buttonHappyPath.cy.js +++ b/cypress-tests/cypress/e2e/editor/widget/buttonHappyPath.cy.js @@ -35,7 +35,7 @@ import { describe("Editor- Test Button widget", () => { beforeEach(() => { cy.apiLogin(); - cy.apiCreateApp(`${fake.companyName}-App`); + cy.apiCreateApp(`${fake.companyName}-button-App`); cy.openApp(); cy.dragAndDropWidget(buttonText.defaultWidgetText, 500, 500); }); @@ -352,7 +352,7 @@ describe("Editor- Test Button widget", () => { cy.wait(500); cy.verifyToastMessage(commonSelectors.toastMessage, data.alertMessage); - cy.get('[data-cy="input-textinput1"]').should( + cy.get(commonWidgetSelector.draggableWidget('textinput1')).should( "have.value", data.customMessage ); @@ -452,6 +452,7 @@ describe("Editor- Test Button widget", () => { cy.apiDeleteApp(); }); it("Should verify deletion of button component from right side panel", () => { + openEditorSidebar(buttonText.defaultWidgetName); cy.get('[data-cy="component-inspector-options"]').click(); cy.get('[data-cy="component-inspector-delete-button"]').click(); cy.get('[data-cy="yes-button"]').click(); diff --git a/cypress-tests/cypress/e2e/editor/widget/componentsBasicHappypath.cy.js b/cypress-tests/cypress/e2e/editor/widget/componentsBasicHappypath.cy.js index 72a92b3c11..4641ab26f0 100644 --- a/cypress-tests/cypress/e2e/editor/widget/componentsBasicHappypath.cy.js +++ b/cypress-tests/cypress/e2e/editor/widget/componentsBasicHappypath.cy.js @@ -417,7 +417,7 @@ describe("Basic components", () => { cy.resizeWidget("form1", 650, 400, false); openEditorSidebar("form1"); - editAndVerifyWidgetName("form2"); + editAndVerifyWidgetName("form2", []); cy.waitForAutoSave(); diff --git a/cypress-tests/cypress/e2e/editor/widget/listViewHappyPath.cy.js b/cypress-tests/cypress/e2e/editor/widget/listViewHappyPath.cy.js index 112aa8d744..c17ef03150 100644 --- a/cypress-tests/cypress/e2e/editor/widget/listViewHappyPath.cy.js +++ b/cypress-tests/cypress/e2e/editor/widget/listViewHappyPath.cy.js @@ -93,6 +93,7 @@ describe("List view widget", () => { ) .realHover() .realClick(); + openEditorSidebar(commonWidgetText.text1); cy.get( '[data-cy="textcomponenttextinput-input-field"] ' ).clearAndTypeOnCodeMirror(codeMirrorInputLabel("listItem.name")); diff --git a/cypress-tests/cypress/e2e/editor/widget/tableRegression.cy.js b/cypress-tests/cypress/e2e/editor/widget/tableRegression.cy.js index ca9d4321e4..16e78eda88 100644 --- a/cypress-tests/cypress/e2e/editor/widget/tableRegression.cy.js +++ b/cypress-tests/cypress/e2e/editor/widget/tableRegression.cy.js @@ -314,7 +314,7 @@ describe("Table", () => { cy.get('[data-cy="inspector-close-icon"]').click(); openEditorSidebar(data.widgetName); - openAccordion(commonWidgetText.accordionLayout, []); + openAccordion('Layout', []); verifyAndModifyToggleFx( "Show on desktop", @@ -885,6 +885,7 @@ describe("Table", () => { }); it("should verify download", () => { + deleteDownloadsFolder(); cy.get(tableSelector.buttonDownloadDropdown).should("be.visible").click(); cy.get(tableSelector.optionDownloadPdf).click(); cy.task("readPdf", "cypress/downloads/all-data.pdf") @@ -1139,7 +1140,7 @@ describe("Table", () => { cy.get(".tooltip-inner").invoke("hide"); verifyNodeData("components", "Object", "1 entry "); openNode("components"); - verifyNodeData(tableText.defaultWidgetName, "Object", "22 entries "); + verifyNodeData(tableText.defaultWidgetName, "Object", "26 entries "); cy.wait(1000); openNode(tableText.defaultWidgetName, 0, 1); // openNode(tableText.defaultWidgetName, 0, 1); @@ -1246,7 +1247,7 @@ describe("Table", () => { '[data-cy="textcomponenttextinput-input-field"]' ).clearAndTypeOnCodeMirror("Column Email"); // verifyAndModifyParameter("Text", "Column Email"); - cy.get('[data-cy="inspector-close-icon"]').click(); + cy.get('[data-cy="inspector-close-icon"]').click({ force: true }); cy.get(`[data-cy="draggable-widget-${commonWidgetText.text1}"]`).should( "have.text", "Column Email" diff --git a/cypress-tests/cypress/e2e/workspace/bulkUserUpload.cy.js b/cypress-tests/cypress/e2e/workspace/bulkUserUpload.cy.js index 2363e5f16b..dea24b3615 100644 --- a/cypress-tests/cypress/e2e/workspace/bulkUserUpload.cy.js +++ b/cypress-tests/cypress/e2e/workspace/bulkUserUpload.cy.js @@ -32,7 +32,6 @@ describe("Bulk user upload", () => { it("Verfiy bulk user upload invalid files", () => { data.firstName = fake.firstName; - data.email = fake.email.toLowerCase(); data.workspaceName = data.firstName.toLowerCase(); cy.apiLogin() @@ -121,7 +120,6 @@ describe("Bulk user upload", () => { it("Verify bulk user upload functionality", () => { data.firstName = fake.firstName; - data.email = fake.email.toLowerCase(); data.workspaceName = data.firstName.toLowerCase(); cy.apiLogin() diff --git a/cypress-tests/cypress/e2e/workspace/dashboard.cy.js b/cypress-tests/cypress/e2e/workspace/dashboard.cy.js index 02847a6785..548e1cea40 100644 --- a/cypress-tests/cypress/e2e/workspace/dashboard.cy.js +++ b/cypress-tests/cypress/e2e/workspace/dashboard.cy.js @@ -165,7 +165,7 @@ describe("dashboard", () => { verifyTooltip(commonSelectors.databaseIcon, "ToolJet Database"); verifyTooltip(commonSelectors.globalDataSourceIcon, "Data sources"); verifyTooltip( - '[data-cy="icon-workspace-constants"]', + commonSelectors.workspaceConstantsIcon, "Workspace constants" ); verifyTooltip(commonSelectors.notificationsIcon, "Comment notifications"); diff --git a/cypress-tests/cypress/e2e/workspace/manageUsers.cy.js b/cypress-tests/cypress/e2e/workspace/manageUsers.cy.js index 64d93fc53f..899fbb4bb2 100644 --- a/cypress-tests/cypress/e2e/workspace/manageUsers.cy.js +++ b/cypress-tests/cypress/e2e/workspace/manageUsers.cy.js @@ -324,7 +324,7 @@ describe("Manage Users", () => { "have.text", "User groups" ); - cy.get(".css-3w2yfm-ValueContainer").should("be.visible"); + cy.get('[data-cy="user-group-select"]>>>>>').should("be.visible"); cy.get(commonSelectors.cancelButton).verifyVisibleElement( "have.text", "Cancel" @@ -333,16 +333,19 @@ describe("Manage Users", () => { "have.text", "Update" ); - cy.get(".css-3w2yfm-ValueContainer").click(); - cy.get(".css-1c6ox7i-Input").type("Admin"); - cy.get(".form-check-input").check(); + + cy.get('[data-cy="user-group-select"]>>>>>').eq(0).type("Admin"); + cy.wait(1000); + cy.get('[data-cy="group-check-input"]').eq(0).check(); + cy.get(commonSelectors.cancelButton).click(); cy.get(usersSelector.userActionButton).click(); cy.get(usersSelector.editUserDetailsButton).click(); - cy.get(".css-3w2yfm-ValueContainer").click(); - cy.get(".css-1c6ox7i-Input").type("Admin"); - cy.get(".form-check-input").check(); + cy.get('[data-cy="user-group-select"]>>>>>').eq(0).type("Admin"); + cy.wait(1000); + cy.get('[data-cy="group-check-input"]').eq(0).check(); + cy.get(usersSelector.buttonInviteUsers).click(); cy.verifyToastMessage( commonSelectors.toastMessage, diff --git a/cypress-tests/cypress/support/utils/button.js b/cypress-tests/cypress/support/utils/button.js index 9f44e44a3f..ddace2f305 100644 --- a/cypress-tests/cypress/support/utils/button.js +++ b/cypress-tests/cypress/support/utils/button.js @@ -106,7 +106,7 @@ export const verifyBasicData = (widgetName, data) => { force: true, }); cy.verifyToastMessage(commonSelectors.toastMessage, data.alertMessage); - cy.get(`[data-cy='input-textinput1']`).should( + cy.get(`[data-cy="draggable-widget-textinput1"]`).should( "have.value", data.customMessage ); diff --git a/cypress-tests/cypress/support/utils/editor/passwordNumberInput.js b/cypress-tests/cypress/support/utils/editor/passwordNumberInput.js index 0e19f58f93..83207d4632 100644 --- a/cypress-tests/cypress/support/utils/editor/passwordNumberInput.js +++ b/cypress-tests/cypress/support/utils/editor/passwordNumberInput.js @@ -45,7 +45,6 @@ export const verifyCSA = (data) => { force: true, }); cy.get(commonWidgetSelector.draggableWidget("textinput1")) - .find("input") .clear() .type(data.customText); cy.get( diff --git a/cypress-tests/cypress/support/utils/events.js b/cypress-tests/cypress/support/utils/events.js index 5441d82bde..7f4776e766 100644 --- a/cypress-tests/cypress/support/utils/events.js +++ b/cypress-tests/cypress/support/utils/events.js @@ -12,10 +12,13 @@ export const selectEvent = ( .click() .find("input") .type(`{selectAll}{backspace}${event}{enter}`); + cy.get('[data-cy="event-label"]').click({force:true}) + cy.get('[data-cy="action-selection"]') .click() .find("input") .type(`{selectAll}{backspace}${action}{enter}`); + cy.get('[data-cy="event-label"]').click({force:true}) cy.wait("@events"); }; @@ -29,14 +32,19 @@ export const selectCSA = ( .click() .find("input") .type(`{selectAll}{backspace}${component}{enter}`); + cy.get('[data-cy="event-label"]').click({force:true}) + cy.get('[data-cy="action-options-action-selection-field"]') .click() .find("input") .type(`{selectAll}{backspace}${componentAction}{enter}`); + cy.get('[data-cy="event-label"]').click({force:true}) + cy.wait("@events"); cy.get('[data-cy="debounce-input-field"]') .click() .type(`{selectAll}{backspace}${debounce}{enter}`); + cy.get('[data-cy="event-label"]').click({force:true}) cy.wait("@events"); }; @@ -45,6 +53,7 @@ export const addSupportCSAData = (field, data) => { cy.get(`[data-cy="event-${field}-input-field"]`) .click({ force: true }) .clearAndTypeOnCodeMirror(data); + cy.get('[data-cy="event-label"]').click({force:true}) }; export const selectSupportCSAData = (option) => { @@ -54,6 +63,7 @@ export const selectSupportCSAData = (option) => { .click() .find("input") .type(`{selectAll}{backspace}${option}{enter}`); + cy.get('[data-cy="event-label"]').click({force:true}) cy.wait("@events"); }; @@ -64,5 +74,6 @@ export const changeEventType = (event, eventIndex = 0) => { .click() .find("input") .type(`{selectAll}{backspace}${event}{enter}`); + cy.get('[data-cy="event-label"]').click({force:true}) cy.wait("@events"); }; diff --git a/cypress-tests/cypress/support/utils/listviewWidget.js b/cypress-tests/cypress/support/utils/listviewWidget.js index 3d00e1eb54..2b1723963e 100644 --- a/cypress-tests/cypress/support/utils/listviewWidget.js +++ b/cypress-tests/cypress/support/utils/listviewWidget.js @@ -95,7 +95,7 @@ export const verifyValuesOnList = ( cy.get(commonWidgetSelector.draggableWidget(childName)).each( ($element, i) => { if (isChild) { - cy.wrap($element).find("input").should(`have.${type}`, value[i]); + cy.wrap($element).should(`have.${type}`, value[i]); } else { cy.wrap($element).should(`have.${type}`, value[i]); } diff --git a/cypress-tests/cypress/support/utils/manageUsers.js b/cypress-tests/cypress/support/utils/manageUsers.js index 1e560db776..57c4362301 100644 --- a/cypress-tests/cypress/support/utils/manageUsers.js +++ b/cypress-tests/cypress/support/utils/manageUsers.js @@ -264,17 +264,15 @@ export const fillUserInviteForm = (firstName, email) => { export const selectUserGroup = (groupName) => { cy.wait(1500); - cy.get("body").then(($body) => { const selectDropdown = $body.find('[data-cy="user-group-select"]>>>>>'); if (selectDropdown.length === 0) { cy.get('[data-cy="user-group-select"]>>>>>').click(); } - cy.get('[data-cy="user-group-select"]>>>>>').eq(0).type(groupName); cy.wait(1000); - cy.get('[data-cy="user-group-select"]>>>>>').eq(2).click(); + cy.get('[data-cy="group-check-input"]').eq(0).check() }); }; @@ -296,11 +294,11 @@ export const inviteUserWithUserGroups = ( } cy.get('[data-cy="user-group-select"]>>>>>').eq(0).type(groupName1); cy.wait(1000); - cy.get('[data-cy="user-group-select"]>>>>>').eq(2).click(); + cy.get('[data-cy="group-check-input"]').eq(0).check() cy.wait(1000); cy.get('[data-cy="user-group-select"]>>>>>').eq(0).type(groupName2); cy.wait(1000); - cy.get('[data-cy="user-group-select"]>>>>>').eq(4).click(); + cy.get('[data-cy="group-check-input"]').eq(0).check() }); cy.get(usersSelector.buttonInviteUsers).click(); diff --git a/docs/docs/Enterprise/superadmin.md b/docs/docs/Enterprise/superadmin.md index 56911fd192..ef91fd711f 100644 --- a/docs/docs/Enterprise/superadmin.md +++ b/docs/docs/Enterprise/superadmin.md @@ -9,7 +9,7 @@ A Super Admin is the user who has full access to all the Workspaces, Users, and The user details entered while setting up ToolJet will have Super Admin privileges. -## How is Super Admin different from Admin +## How Super Admin is different from Admin | Privilege | Admin | Super Admin | | --------- | ----- | ----------- | @@ -24,34 +24,30 @@ The user details entered while setting up ToolJet will have Super Admin privileg | [Access any user's ToolJet database (create, edit or delete database)](#access-tooljet-db-in-any-workspace) | ❌ | ✅ | | [Manage any workspace's setting (Groups/SSO/Workspace constants)](#manage-workspace-setting-groupsssoworkspace-constants) | ❌ | ✅ | | [Manage all users from all the workspaces in the instance](#manage-all-users-in-the-instance) | ❌ | ✅ | +| [Archive/Unarchive any user from all the workspaces in the instance](#archiving-a-user-from-all-the-workspaces-instance-level) | ❌ | ✅ | +| [Reset password of any user](#reset-password-of-any-user) | ❌ | ✅ | +| [Edit name of any user](#edit-name) | ❌ | ✅ | | [Make any user Super Admin](#make-the-user-super-admin) | ❌ | ✅ | +| [Manage all workspaces in the instance(Archive/Unarchive)](#all-workspaces) | ❌ | ✅ | | [Restrict creation of personal workspace of users](#restrict-creation-of-personal-workspace-of-users) | ❌ | ✅ | | [Enable Multiplayer editing](#enable-multiplayer-editing) | ❌ | ✅ | | [Implement White Labelling](#white-labelling) | ❌ | ✅ | -
-
-
-
+
-
+
+
-
+
-
+
-
+
+
+## All workspaces
+The All Workspaces tab provides a comprehensive view of all workspaces within the ToolJet instance. Super Admins can use this functionality to monitor and manage workspaces collectively, ensuring efficient administration and organization-wide oversight.
+
+Super Admins have the authority to **archive** or **unarchive** workspaces of any user in the instance as needed. Archiving a workspace essentially sets it to an inactive state, removing it from active use. Conversely, unarchiving reactivates a previously archived workspace, making it accessible once again.
+
+
+
+
+
+
-
-
-
-
+
+
-
-
-
-
-
-
+
+## Creating a new app and runJS query
-
+
+After creating and running the query, an alert should pop up with the message "Mathjs and Flatten imported."
-
+
-
-
+
+
+
+2. Paste the following code into the RunJS query editor. This code utilizes the `ReferenceError` constructor to intentionally generate an error.
+ ```js
+ throw new ReferenceError('This is a reference error.');
+ ```
-
+
+
+
+
+
+
+
+
+
+
+
+
+Begin by creating a new application in the ToolJet dashboard. Once the app builder opens, Drag a table component onto the canvas. This component will display the data fetched from the REST API query.
-
+
+## Step 2: Set Up a REST API Query
-
+
+## Step 3: Configure Table Properties
-
+
+
+
-
-
+
-
-
+
-
-
+
-
-
+
-
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
+
+
-
-
+
+
+
-
+
-
+
+
+
+
+- Under **General Settings** section, toggle **Password Login** to enable/disable it.
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
+
-
+
-
+
+6. Finally, click on the **Save changes** button and the GitHub sign-in button will now be available in your ToolJet login screen.
-
+To set GitHub as the default SSO for the instance, use the following environment variables:
-
+
+
-
+
+
diff --git a/docs/versioned_docs/version-2.1.0/security.md b/docs/versioned_docs/version-2.1.0/security.md
index 0862a06f41..27790381a6 100644
--- a/docs/versioned_docs/version-2.1.0/security.md
+++ b/docs/versioned_docs/version-2.1.0/security.md
@@ -21,7 +21,7 @@ All the datasource credentials are securely encrypted using `aes-256-gcm`. The c
- **TLS**: If you are using ToolJet cloud, all connections are encrypted using TLS. We also have documentation for setting up TLS for self-hosted installations of ToolJet.
- **Audit logs**: Audit logs are available on the enterprise edition of ToolJet. Every user action is logged along with the IP addresses and user information.
- **Request logging**: All the requests to server are logged. If self-hosted, you can easily extend ToolJet to use your preferred logging service. ToolJet comes with built-in Sentry integration.
-- **Whitelisted IPs**: If you are using ToolJet cloud, you can whitelist our IP address (3.129.198.40) so that your datasources are not exposed to the public.
+- **Whitelisted IPs**: If you are using ToolJet cloud, you can whitelist our IP address (34.86.81.252) so that your datasources are not exposed to the public.
- **Backups**: ToolJet cloud is hosted on AWS using EKS with autoscaling and regular backups.
If you notice a security vulnerability, please let the team know by sending an email to `security@tooljet.com`.
diff --git a/docs/versioned_docs/version-2.1.0/setup/google-cloud-run.md b/docs/versioned_docs/version-2.1.0/setup/google-cloud-run.md
index 8fae7cf56e..7ba4958d41 100644
--- a/docs/versioned_docs/version-2.1.0/setup/google-cloud-run.md
+++ b/docs/versioned_docs/version-2.1.0/setup/google-cloud-run.md
@@ -46,7 +46,7 @@ Follow the steps below to deploy ToolJet on Cloud run with `gcloud` CLI.
diff --git a/docs/versioned_docs/version-2.10.0/security.md b/docs/versioned_docs/version-2.10.0/security.md
index 0862a06f41..27790381a6 100644
--- a/docs/versioned_docs/version-2.10.0/security.md
+++ b/docs/versioned_docs/version-2.10.0/security.md
@@ -21,7 +21,7 @@ All the datasource credentials are securely encrypted using `aes-256-gcm`. The c
- **TLS**: If you are using ToolJet cloud, all connections are encrypted using TLS. We also have documentation for setting up TLS for self-hosted installations of ToolJet.
- **Audit logs**: Audit logs are available on the enterprise edition of ToolJet. Every user action is logged along with the IP addresses and user information.
- **Request logging**: All the requests to server are logged. If self-hosted, you can easily extend ToolJet to use your preferred logging service. ToolJet comes with built-in Sentry integration.
-- **Whitelisted IPs**: If you are using ToolJet cloud, you can whitelist our IP address (3.129.198.40) so that your datasources are not exposed to the public.
+- **Whitelisted IPs**: If you are using ToolJet cloud, you can whitelist our IP address (34.86.81.252) so that your datasources are not exposed to the public.
- **Backups**: ToolJet cloud is hosted on AWS using EKS with autoscaling and regular backups.
If you notice a security vulnerability, please let the team know by sending an email to `security@tooljet.com`.
diff --git a/docs/versioned_docs/version-2.10.0/setup/google-cloud-run.md b/docs/versioned_docs/version-2.10.0/setup/google-cloud-run.md
index 3d5e7e0344..d15e0b2c56 100644
--- a/docs/versioned_docs/version-2.10.0/setup/google-cloud-run.md
+++ b/docs/versioned_docs/version-2.10.0/setup/google-cloud-run.md
@@ -46,13 +46,25 @@ Follow the steps below to deploy ToolJet on Cloud run with `gcloud` CLI.
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
diff --git a/docs/versioned_docs/version-2.22.0/org-management/workspaces/workspace_constants.md b/docs/versioned_docs/version-2.22.0/org-management/workspaces/workspace_constants.md
index 5b65b05b8a..e17f890eb4 100644
--- a/docs/versioned_docs/version-2.22.0/org-management/workspaces/workspace_constants.md
+++ b/docs/versioned_docs/version-2.22.0/org-management/workspaces/workspace_constants.md
@@ -5,6 +5,10 @@ title: Workspace Constants
Workspace constants are predefined values(usually tokens/secret keys/API keys) that can be used across your application to maintain consistency and facilitate easy updates. They allow you to store important data or configurations that should remain unchanged during the application's runtime. This doc will guide you through the usage and management of workspace constants within your workspaces.
+:::danger
+Workspace constants are handled server-side and are not intended for use in query transformations or RunJS and RunPy queries. For these operations, employ variables and page variables instead.
+:::
+
## Environment-Specific Configurations
Users can define environment-specific configurations by setting different values for constants across environments. It is useful for managing sensitive information such as API keys, database credentials, or external service endpoints. For Community edition only production environment is available and for Cloud/EE we will have multi environments (development, staging, production).
diff --git a/docs/versioned_docs/version-2.22.0/security.md b/docs/versioned_docs/version-2.22.0/security.md
index 0862a06f41..27790381a6 100644
--- a/docs/versioned_docs/version-2.22.0/security.md
+++ b/docs/versioned_docs/version-2.22.0/security.md
@@ -21,7 +21,7 @@ All the datasource credentials are securely encrypted using `aes-256-gcm`. The c
- **TLS**: If you are using ToolJet cloud, all connections are encrypted using TLS. We also have documentation for setting up TLS for self-hosted installations of ToolJet.
- **Audit logs**: Audit logs are available on the enterprise edition of ToolJet. Every user action is logged along with the IP addresses and user information.
- **Request logging**: All the requests to server are logged. If self-hosted, you can easily extend ToolJet to use your preferred logging service. ToolJet comes with built-in Sentry integration.
-- **Whitelisted IPs**: If you are using ToolJet cloud, you can whitelist our IP address (3.129.198.40) so that your datasources are not exposed to the public.
+- **Whitelisted IPs**: If you are using ToolJet cloud, you can whitelist our IP address (34.86.81.252) so that your datasources are not exposed to the public.
- **Backups**: ToolJet cloud is hosted on AWS using EKS with autoscaling and regular backups.
If you notice a security vulnerability, please let the team know by sending an email to `security@tooljet.com`.
diff --git a/docs/versioned_docs/version-2.22.0/setup/google-cloud-run.md b/docs/versioned_docs/version-2.22.0/setup/google-cloud-run.md
index 3034395e2f..39c00b19cf 100644
--- a/docs/versioned_docs/version-2.22.0/setup/google-cloud-run.md
+++ b/docs/versioned_docs/version-2.22.0/setup/google-cloud-run.md
@@ -46,13 +46,25 @@ Follow the steps below to deploy ToolJet on Cloud run with `gcloud` CLI.
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
+
+
-
-
-
-
+
+
-
-
-
-
-
-
+
+## Creating a new app and runJS query
-
+
+After creating and running the query, an alert should pop up with the message "Mathjs and Flatten imported."
-
+
-
-
+
+
+
+2. Paste the following code into the RunJS query editor. This code utilizes the `ReferenceError` constructor to intentionally generate an error.
+ ```js
+ throw new ReferenceError('This is a reference error.');
+ ```
-
+
+
+
+
+
+
+
+
+
+
+
+
+Begin by creating a new application in the ToolJet dashboard. Once the app builder opens, Drag a table component onto the canvas. This component will display the data fetched from the REST API query.
-
+
+## Step 2: Set Up a REST API Query
-
+
+## Step 3: Configure Table Properties
-
+
+
+
-
-
+
-
-
+
-
-
+
-
-
+
-
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
+
+
-
-
-
-
+
+
-
-
-
-
-
-
+
+## Creating a new app and runJS query
-
+
+After creating and running the query, an alert should pop up with the message "Mathjs and Flatten imported."
-
+
-
-
+
+
+
+2. Paste the following code into the RunJS query editor. This code utilizes the `ReferenceError` constructor to intentionally generate an error.
+ ```js
+ throw new ReferenceError('This is a reference error.');
+ ```
-
+
+
+
+
+
+
+
+
+
+
+
+
+Begin by creating a new application in the ToolJet dashboard. Once the app builder opens, Drag a table component onto the canvas. This component will display the data fetched from the REST API query.
-
+
+## Step 2: Set Up a REST API Query
-
+
+## Step 3: Configure Table Properties
-
+
+
+
-
-
+
-
-
+
-
-
+
-
-
+
-
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-
-
-
+
-
+
+
-
+
-
+
-
+
+
+## All workspaces
+The All Workspaces tab provides a comprehensive view of all workspaces within the ToolJet instance. Super Admins can use this functionality to monitor and manage workspaces collectively, ensuring efficient administration and organization-wide oversight.
+
+Super Admins have the authority to **archive** or **unarchive** workspaces of any user in the instance as needed. Archiving a workspace essentially sets it to an inactive state, removing it from active use. Conversely, unarchiving reactivates a previously archived workspace, making it accessible once again.
+
+
+
+
+
+
-
-
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
+
+
-
-
+
+
+
-
+
-
+
+
+
+
+- Under **General Settings** section, toggle **Password Login** to enable/disable it.
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
+
-
+
-
+
+6. Finally, click on the **Save changes** button and the GitHub sign-in button will now be available in your ToolJet login screen.
-
+To set GitHub as the default SSO for the instance, use the following environment variables:
-
+
+
diff --git a/docs/versioned_docs/version-2.30.0/Enterprise/superadmin.md b/docs/versioned_docs/version-2.30.0/Enterprise/superadmin.md
index 56911fd192..ef91fd711f 100644
--- a/docs/versioned_docs/version-2.30.0/Enterprise/superadmin.md
+++ b/docs/versioned_docs/version-2.30.0/Enterprise/superadmin.md
@@ -9,7 +9,7 @@ A Super Admin is the user who has full access to all the Workspaces, Users, and
The user details entered while setting up ToolJet will have Super Admin privileges.
-## How is Super Admin different from Admin
+## How Super Admin is different from Admin
| Privilege | Admin | Super Admin |
| --------- | ----- | ----------- |
@@ -24,34 +24,30 @@ The user details entered while setting up ToolJet will have Super Admin privileg
| [Access any user's ToolJet database (create, edit or delete database)](#access-tooljet-db-in-any-workspace) | ❌ | ✅ |
| [Manage any workspace's setting (Groups/SSO/Workspace constants)](#manage-workspace-setting-groupsssoworkspace-constants) | ❌ | ✅ |
| [Manage all users from all the workspaces in the instance](#manage-all-users-in-the-instance) | ❌ | ✅ |
+| [Archive/Unarchive any user from all the workspaces in the instance](#archiving-a-user-from-all-the-workspaces-instance-level) | ❌ | ✅ |
+| [Reset password of any user](#reset-password-of-any-user) | ❌ | ✅ |
+| [Edit name of any user](#edit-name) | ❌ | ✅ |
| [Make any user Super Admin](#make-the-user-super-admin) | ❌ | ✅ |
+| [Manage all workspaces in the instance(Archive/Unarchive)](#all-workspaces) | ❌ | ✅ |
| [Restrict creation of personal workspace of users](#restrict-creation-of-personal-workspace-of-users) | ❌ | ✅ |
| [Enable Multiplayer editing](#enable-multiplayer-editing) | ❌ | ✅ |
| [Implement White Labelling](#white-labelling) | ❌ | ✅ |
-
-
-
-
+
-
+
+
-
+
-
+
-
+
+
+## All workspaces
+The All Workspaces tab provides a comprehensive view of all workspaces within the ToolJet instance. Super Admins can use this functionality to monitor and manage workspaces collectively, ensuring efficient administration and organization-wide oversight.
+
+Super Admins have the authority to **archive** or **unarchive** workspaces of any user in the instance as needed. Archiving a workspace essentially sets it to an inactive state, removing it from active use. Conversely, unarchiving reactivates a previously archived workspace, making it accessible once again.
+
+
+
+
+
+
-
-
-
-
+
+
-
-
-
-
-
-
+
+## Creating a new app and runJS query
-
+
+After creating and running the query, an alert should pop up with the message "Mathjs and Flatten imported."
-
+
-
-
+
+
+
+2. Paste the following code into the RunJS query editor. This code utilizes the `ReferenceError` constructor to intentionally generate an error.
+ ```js
+ throw new ReferenceError('This is a reference error.');
+ ```
-
+
+
+
+
+
+
+
+
+
+
+
+
+Begin by creating a new application in the ToolJet dashboard. Once the app builder opens, Drag a table component onto the canvas. This component will display the data fetched from the REST API query.
-
+
+## Step 2: Set Up a REST API Query
-
+
+## Step 3: Configure Table Properties
-
+
+
+
-
-
+
-
-
+
-
-
+
-
-
+
-
+
+
+
+
+
+
-
-
+
+
+
-
+
-
+
+
+
+
+- Under **General Settings** section, toggle **Password Login** to enable/disable it.
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
+
-
+
-
+
+6. Finally, click on the **Save changes** button and the GitHub sign-in button will now be available in your ToolJet login screen.
-
+To set GitHub as the default SSO for the instance, use the following environment variables:
-
+
+
-
+
+
diff --git a/docs/versioned_docs/version-2.5.0/security.md b/docs/versioned_docs/version-2.5.0/security.md
index 0862a06f41..27790381a6 100644
--- a/docs/versioned_docs/version-2.5.0/security.md
+++ b/docs/versioned_docs/version-2.5.0/security.md
@@ -21,7 +21,7 @@ All the datasource credentials are securely encrypted using `aes-256-gcm`. The c
- **TLS**: If you are using ToolJet cloud, all connections are encrypted using TLS. We also have documentation for setting up TLS for self-hosted installations of ToolJet.
- **Audit logs**: Audit logs are available on the enterprise edition of ToolJet. Every user action is logged along with the IP addresses and user information.
- **Request logging**: All the requests to server are logged. If self-hosted, you can easily extend ToolJet to use your preferred logging service. ToolJet comes with built-in Sentry integration.
-- **Whitelisted IPs**: If you are using ToolJet cloud, you can whitelist our IP address (3.129.198.40) so that your datasources are not exposed to the public.
+- **Whitelisted IPs**: If you are using ToolJet cloud, you can whitelist our IP address (34.86.81.252) so that your datasources are not exposed to the public.
- **Backups**: ToolJet cloud is hosted on AWS using EKS with autoscaling and regular backups.
If you notice a security vulnerability, please let the team know by sending an email to `security@tooljet.com`.
diff --git a/docs/versioned_docs/version-2.5.0/setup/google-cloud-run.md b/docs/versioned_docs/version-2.5.0/setup/google-cloud-run.md
index 3d5e7e0344..d15e0b2c56 100644
--- a/docs/versioned_docs/version-2.5.0/setup/google-cloud-run.md
+++ b/docs/versioned_docs/version-2.5.0/setup/google-cloud-run.md
@@ -46,13 +46,25 @@ Follow the steps below to deploy ToolJet on Cloud run with `gcloud` CLI.
+
+
+
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+
-4. Under containers tab, please make sure the port is set 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity is set to 2GiB.
+4. Under containers tab, please make sure the port is set to 3000 and command `npm, run, start:prod` is entered in container argument field with CPU capacity set to 2GiB:
+
+
+