feat: code split files based on feature flags (#27678)

## Description
Add feature flag based logic for code splitted files

#### PR fixes following issue(s)
Fixes #2237 

#### Type of change

- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing
functionality to not work as expected)


## Testing
>
#### How Has This Been Tested?
> Please describe the tests that you ran to verify your changes. Also
list any relevant details for your test configuration.
> Delete anything that is not relevant
- [x] Manual
- [ ] JUnit
- [ ] Jest
- [x] Cypress
>
>
#### Test Plan
> Add Testsmith test cases links that relate to this PR
>
>
#### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
>
>
>
## Checklist:
#### Dev activity
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag


#### QA activity:
- [ ] [Speedbreak
features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-)
have been covered
- [ ] Test plan covers all impacted features and [areas of
interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-)
- [ ] Test plan has been peer reviewed by project stakeholders and other
QA members
- [ ] Manually tested functionality on DP
- [ ] We had an implementation alignment call with stakeholders post QA
Round 2
- [ ] Cypress test cases have been added and approved by SDET/manual QA
- [ ] Added `Test Plan Approved` label after Cypress tests were reviewed
- [ ] Added `Test Plan Approved` label after JUnit tests were reviewed
This commit is contained in:
Dipyaman Biswas 2023-09-30 02:12:56 +05:30 committed by GitHub
parent 7585a39325
commit 6c0dc2e89f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 709 additions and 232 deletions

View File

@ -56,7 +56,6 @@ import {
fetchProductAlertInit, fetchProductAlertInit,
} from "actions/userActions"; } from "actions/userActions";
import { getCurrentTenant } from "@appsmith/actions/tenantActions"; import { getCurrentTenant } from "@appsmith/actions/tenantActions";
import { getDefaultAdminSettingsPath } from "@appsmith/utils/adminSettingsHelpers";
import { getCurrentUser as getCurrentUserSelector } from "selectors/usersSelectors"; import { getCurrentUser as getCurrentUserSelector } from "selectors/usersSelectors";
import { import {
getTenantPermissions, getTenantPermissions,
@ -67,6 +66,9 @@ import RouteChangeListener from "RouteChangeListener";
import { initCurrentPage } from "../actions/initActions"; import { initCurrentPage } from "../actions/initActions";
import Walkthrough from "components/featureWalkthrough"; import Walkthrough from "components/featureWalkthrough";
import ProductAlertBanner from "components/editorComponents/ProductAlertBanner"; import ProductAlertBanner from "components/editorComponents/ProductAlertBanner";
import { getAdminSettingsPath } from "@appsmith/utils/BusinessFeatures/adminSettingsHelpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
export const SentryRoute = Sentry.withSentryRouting(Route); export const SentryRoute = Sentry.withSentryRouting(Route);
@ -75,6 +77,7 @@ export const loadingIndicator = <PageLoadingBar />;
export function Routes() { export function Routes() {
const user = useSelector(getCurrentUserSelector); const user = useSelector(getCurrentUserSelector);
const tenantPermissions = useSelector(getTenantPermissions); const tenantPermissions = useSelector(getTenantPermissions);
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
return ( return (
<Switch> <Switch>
@ -99,10 +102,11 @@ export function Routes() {
to={ to={
!user !user
? ADMIN_SETTINGS_PATH ? ADMIN_SETTINGS_PATH
: getDefaultAdminSettingsPath({ : getAdminSettingsPath(
isSuperUser: user?.isSuperUser || false, isFeatureEnabled,
user?.isSuperUser || false,
tenantPermissions, tenantPermissions,
}) )
} }
/> />
<SentryRoute <SentryRoute

View File

@ -26,6 +26,7 @@ export const FEATURE_FLAG = {
ab_mock_mongo_schema_enabled: "ab_mock_mongo_schema_enabled", ab_mock_mongo_schema_enabled: "ab_mock_mongo_schema_enabled",
release_show_publish_app_to_community_enabled: release_show_publish_app_to_community_enabled:
"release_show_publish_app_to_community_enabled", "release_show_publish_app_to_community_enabled",
license_gac_enabled: "license_gac_enabled",
} as const; } as const;
export type FeatureFlag = keyof typeof FEATURE_FLAG; export type FeatureFlag = keyof typeof FEATURE_FLAG;
@ -53,6 +54,7 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = {
deprecate_custom_fusioncharts_enabled: false, deprecate_custom_fusioncharts_enabled: false,
ab_mock_mongo_schema_enabled: false, ab_mock_mongo_schema_enabled: false,
release_show_publish_app_to_community_enabled: false, release_show_publish_app_to_community_enabled: false,
license_gac_enabled: false,
}; };
export const AB_TESTING_EVENT_KEYS = { export const AB_TESTING_EVENT_KEYS = {

View File

@ -1,18 +1,21 @@
import { APPLICATIONS_URL } from "constants/routes"; import { APPLICATIONS_URL } from "constants/routes";
import { showAdminSettings } from "@appsmith/utils/adminSettingsHelpers";
import React from "react"; import React from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import type { RouteComponentProps } from "react-router"; import type { RouteComponentProps } from "react-router";
import { Redirect } from "react-router"; import { Redirect } from "react-router";
import { getCurrentUser } from "selectors/usersSelectors"; import { getCurrentUser } from "selectors/usersSelectors";
import { getShowAdminSettings } from "@appsmith/utils/BusinessFeatures/adminSettingsHelpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
export default function WithSuperUserHOC( export default function WithSuperUserHOC(
Component: React.ComponentType<RouteComponentProps>, Component: React.ComponentType<RouteComponentProps>,
) { ) {
return function Wrapped(props: RouteComponentProps) { return function Wrapped(props: RouteComponentProps) {
const user = useSelector(getCurrentUser); const user = useSelector(getCurrentUser);
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
if (!user) return null; if (!user) return null;
if (!showAdminSettings(user)) { if (!getShowAdminSettings(isFeatureEnabled, user)) {
return <Redirect to={APPLICATIONS_URL} />; return <Redirect to={APPLICATIONS_URL} />;
} }
return <Component {...props} />; return <Component {...props} />;

View File

@ -86,7 +86,6 @@ import RepoLimitExceededErrorModal from "pages/Editor/gitSync/RepoLimitExceededE
import { resetEditorRequest } from "actions/initActions"; import { resetEditorRequest } from "actions/initActions";
import { import {
hasCreateNewAppPermission, hasCreateNewAppPermission,
hasCreateWorkspacePermission,
hasDeleteWorkspacePermission, hasDeleteWorkspacePermission,
isPermitted, isPermitted,
PERMISSION_TYPE, PERMISSION_TYPE,
@ -100,6 +99,9 @@ import { usePackage } from "@appsmith/pages/Applications/helpers";
import PackageCardList from "@appsmith/pages/Applications/PackageCardList"; import PackageCardList from "@appsmith/pages/Applications/PackageCardList";
import WorkspaceAction from "@appsmith/pages/Applications/WorkspaceAction"; import WorkspaceAction from "@appsmith/pages/Applications/WorkspaceAction";
import ResourceListLoader from "@appsmith/pages/Applications/ResourceListLoader"; import ResourceListLoader from "@appsmith/pages/Applications/ResourceListLoader";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasCreateWorkspacePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
export const { cloudHosting } = getAppsmithConfigs(); export const { cloudHosting } = getAppsmithConfigs();
@ -314,6 +316,7 @@ export function LeftPane(props: LeftPaneProps) {
const fetchedUserWorkspaces = useSelector(getUserApplicationsWorkspaces); const fetchedUserWorkspaces = useSelector(getUserApplicationsWorkspaces);
const isFetchingApplications = useSelector(getIsFetchingApplications); const isFetchingApplications = useSelector(getIsFetchingApplications);
const isMobile = useIsMobileDevice(); const isMobile = useIsMobileDevice();
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
let userWorkspaces; let userWorkspaces;
if (!isFetchingApplications) { if (!isFetchingApplications) {
@ -323,7 +326,10 @@ export function LeftPane(props: LeftPaneProps) {
} }
const tenantPermissions = useSelector(getTenantPermissions); const tenantPermissions = useSelector(getTenantPermissions);
const canCreateWorkspace = hasCreateWorkspacePermission(tenantPermissions); const canCreateWorkspace = getHasCreateWorkspacePermission(
isFeatureEnabled,
tenantPermissions,
);
const location = useLocation(); const location = useLocation();
const urlHash = location.hash.slice(1); const urlHash = location.hash.slice(1);

View File

@ -0,0 +1,30 @@
import type { User } from "constants/userConstants";
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { showAdminSettings as showAdminSettings_CE } from "ce/utils/adminSettingsHelpers";
import { showAdminSettings as showAdminSettings_EE } from "@appsmith/utils/adminSettingsHelpers";
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { getDefaultAdminSettingsPath as getDefaultAdminSettingsPath_CE } from "ce/utils/adminSettingsHelpers";
import { getDefaultAdminSettingsPath as getDefaultAdminSettingsPath_EE } from "@appsmith/utils/adminSettingsHelpers";
export const getShowAdminSettings = (
isEnabled: boolean,
user: User | undefined,
) => {
if (isEnabled) {
return showAdminSettings_EE(user);
} else {
return showAdminSettings_CE(user);
}
};
export const getAdminSettingsPath = (
isEnabled: boolean,
isSuperUser: boolean | undefined,
tenantPermissions: string[] = [],
) => {
if (isEnabled) {
return getDefaultAdminSettingsPath_EE({ isSuperUser, tenantPermissions });
} else {
return getDefaultAdminSettingsPath_CE({ isSuperUser, tenantPermissions });
}
};

View File

@ -0,0 +1,143 @@
/* eslint-disable @typescript-eslint/no-restricted-imports */
import { hasCreateWorkspacePermission as hasCreateWorkspacePermission_CE } from "ce/utils/permissionHelpers";
import { hasCreateWorkspacePermission as hasCreateWorkspacePermission_EE } from "@appsmith/utils/permissionHelpers";
import { hasCreateDatasourcePermission as hasCreateDatasourcePermission_CE } from "ce/utils/permissionHelpers";
import { hasCreateDatasourcePermission as hasCreateDatasourcePermission_EE } from "@appsmith/utils/permissionHelpers";
import { hasManageDatasourcePermission as hasManageDatasourcePermission_CE } from "ce/utils/permissionHelpers";
import { hasManageDatasourcePermission as hasManageDatasourcePermission_EE } from "@appsmith/utils/permissionHelpers";
import { hasDeleteDatasourcePermission as hasDeleteDatasourcePermission_CE } from "ce/utils/permissionHelpers";
import { hasDeleteDatasourcePermission as hasDeleteDatasourcePermission_EE } from "@appsmith/utils/permissionHelpers";
import { hasCreateDatasourceActionPermission as hasCreateDatasourceActionPermission_CE } from "ce/utils/permissionHelpers";
import { hasCreateDatasourceActionPermission as hasCreateDatasourceActionPermission_EE } from "@appsmith/utils/permissionHelpers";
import { hasCreatePagePermission as hasCreatePagePermission_CE } from "ce/utils/permissionHelpers";
import { hasCreatePagePermission as hasCreatePagePermission_EE } from "@appsmith/utils/permissionHelpers";
import { hasManagePagePermission as hasManagePagePermission_CE } from "ce/utils/permissionHelpers";
import { hasManagePagePermission as hasManagePagePermission_EE } from "@appsmith/utils/permissionHelpers";
import { hasDeletePagePermission as hasDeletePagePermission_CE } from "ce/utils/permissionHelpers";
import { hasDeletePagePermission as hasDeletePagePermission_EE } from "@appsmith/utils/permissionHelpers";
import { hasCreateActionPermission as hasCreateActionPermission_CE } from "ce/utils/permissionHelpers";
import { hasCreateActionPermission as hasCreateActionPermission_EE } from "@appsmith/utils/permissionHelpers";
import { hasManageActionPermission as hasManageActionPermission_CE } from "ce/utils/permissionHelpers";
import { hasManageActionPermission as hasManageActionPermission_EE } from "@appsmith/utils/permissionHelpers";
import { hasDeleteActionPermission as hasDeleteActionPermission_CE } from "ce/utils/permissionHelpers";
import { hasDeleteActionPermission as hasDeleteActionPermission_EE } from "@appsmith/utils/permissionHelpers";
import { hasExecuteActionPermission as hasExecuteActionPermission_CE } from "ce/utils/permissionHelpers";
import { hasExecuteActionPermission as hasExecuteActionPermission_EE } from "@appsmith/utils/permissionHelpers";
import { hasAuditLogsReadPermission as hasAuditLogsReadPermission_CE } from "ce/utils/permissionHelpers";
import { hasAuditLogsReadPermission as hasAuditLogsReadPermission_EE } from "@appsmith/utils/permissionHelpers";
export const getHasCreateWorkspacePermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasCreateWorkspacePermission_EE(permissions);
else return hasCreateWorkspacePermission_CE(permissions);
};
export const getHasCreateDatasourcePermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasCreateDatasourcePermission_EE(permissions);
else return hasCreateDatasourcePermission_CE(permissions);
};
export const getHasManageDatasourcePermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasManageDatasourcePermission_EE(permissions);
else return hasManageDatasourcePermission_CE(permissions);
};
export const getHasDeleteDatasourcePermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasDeleteDatasourcePermission_EE(permissions);
else return hasDeleteDatasourcePermission_CE(permissions);
};
export const getHasCreateDatasourceActionPermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasCreateDatasourceActionPermission_EE(permissions);
else return hasCreateDatasourceActionPermission_CE(permissions);
};
export const getHasCreatePagePermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasCreatePagePermission_EE(permissions);
else return hasCreatePagePermission_CE(permissions);
};
export const getHasManagePagePermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasManagePagePermission_EE(permissions);
else return hasManagePagePermission_CE(permissions);
};
export const getHasDeletePagePermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasDeletePagePermission_EE(permissions);
else return hasDeletePagePermission_CE(permissions);
};
export const getHasCreateActionPermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasCreateActionPermission_EE(permissions);
else return hasCreateActionPermission_CE(permissions);
};
export const getHasManageActionPermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasManageActionPermission_EE(permissions);
else return hasManageActionPermission_CE(permissions);
};
export const getHasDeleteActionPermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasDeleteActionPermission_EE(permissions);
else return hasDeleteActionPermission_CE(permissions);
};
export const getHasExecuteActionPermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasExecuteActionPermission_EE(permissions);
else return hasExecuteActionPermission_CE(permissions);
};
export const getHasAuditLogsReadPermission = (
isEnabled: boolean,
permissions?: string[],
) => {
if (isEnabled) return hasAuditLogsReadPermission_EE(permissions);
else return hasAuditLogsReadPermission_CE(permissions);
};

View File

@ -33,7 +33,7 @@ export const saveAllowed = (
/* get default admin settings path */ /* get default admin settings path */
export const getDefaultAdminSettingsPath = ( export const getDefaultAdminSettingsPath = (
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
{ isSuperUser, tenantPermissions = [] }: Record<string, any>, { isSuperUser, tenantPermissions: any = [] }: Record<string, any>,
): string => { ): string => {
return ADMIN_SETTINGS_CATEGORY_DEFAULT_PATH; return ADMIN_SETTINGS_CATEGORY_DEFAULT_PATH;
}; };

View File

@ -13,6 +13,10 @@ export const isSAMLEnabled = (featureFlags: FeatureFlags) => {
return featureFlags?.license_sso_saml_enabled; return featureFlags?.license_sso_saml_enabled;
}; };
export const isGACEnabled = (featureFlags: FeatureFlags) => {
return featureFlags?.license_gac_enabled;
};
export const isMultipleEnvEnabled = (featureFlags: FeatureFlags) => { export const isMultipleEnvEnabled = (featureFlags: FeatureFlags) => {
return featureFlags?.release_datasource_environments_enabled; return featureFlags?.release_datasource_environments_enabled;
}; };

View File

@ -28,7 +28,6 @@ import {
getPagePermissions, getPagePermissions,
} from "selectors/editorSelectors"; } from "selectors/editorSelectors";
import { builderURL } from "RouteBuilder"; import { builderURL } from "RouteBuilder";
import { hasManagePagePermission } from "@appsmith/utils/permissionHelpers";
import DatasourceStructureHeader from "pages/Editor/Explorer/Datasources/DatasourceStructureHeader"; import DatasourceStructureHeader from "pages/Editor/Explorer/Datasources/DatasourceStructureHeader";
import { import {
DatasourceStructureContainer as DataStructureList, DatasourceStructureContainer as DataStructureList,
@ -59,6 +58,9 @@ import { getIsFirstTimeUserOnboardingEnabled } from "selectors/onboardingSelecto
import history from "utils/history"; import history from "utils/history";
import { SignpostingWalkthroughConfig } from "pages/Editor/FirstTimeUserOnboarding/Utils"; import { SignpostingWalkthroughConfig } from "pages/Editor/FirstTimeUserOnboarding/Utils";
import { getAssetUrl } from "@appsmith/utils/airgapHelpers"; import { getAssetUrl } from "@appsmith/utils/airgapHelpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasManagePagePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const SCHEMA_GUIDE_GIF = `${ASSETS_CDN_URL}/schema.gif`; const SCHEMA_GUIDE_GIF = `${ASSETS_CDN_URL}/schema.gif`;
@ -421,7 +423,12 @@ function ActionSidebar({
const pagePermissions = useSelector(getPagePermissions); const pagePermissions = useSelector(getPagePermissions);
const canEditPage = hasManagePagePermission(pagePermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canEditPage = getHasManagePagePermission(
isFeatureEnabled,
pagePermissions,
);
const showSuggestedWidgets = const showSuggestedWidgets =
canEditPage && hasResponse && suggestedWidgets && !!suggestedWidgets.length; canEditPage && hasResponse && suggestedWidgets && !!suggestedWidgets.length;

View File

@ -26,15 +26,17 @@ import { PluginType } from "entities/Action";
import { integrationEditorURL } from "RouteBuilder"; import { integrationEditorURL } from "RouteBuilder";
import { EntityIcon } from "pages/Editor/Explorer/ExplorerIcons"; import { EntityIcon } from "pages/Editor/Explorer/ExplorerIcons";
import { createNewQueryAction } from "actions/apiPaneActions"; import { createNewQueryAction } from "actions/apiPaneActions";
import {
hasCreateActionPermission,
hasCreateDatasourceActionPermission,
hasCreateDatasourcePermission,
} from "@appsmith/utils/permissionHelpers";
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors"; import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors";
import { importRemixIcon } from "design-system-old"; import { importRemixIcon } from "design-system-old";
import AnalyticsUtil from "utils/AnalyticsUtil"; import AnalyticsUtil from "utils/AnalyticsUtil";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import {
getHasCreateActionPermission,
getHasCreateDatasourceActionPermission,
getHasCreateDatasourcePermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const AddLineIcon = importRemixIcon( const AddLineIcon = importRemixIcon(
() => import("remixicon-react/AddLineIcon"), () => import("remixicon-react/AddLineIcon"),
); );
@ -72,9 +74,15 @@ export const useFilteredFileOperations = (query = "") => {
const pagePermissions = useSelector(getPagePermissions); const pagePermissions = useSelector(getPagePermissions);
const canCreateActions = hasCreateActionPermission(pagePermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreateDatasource = hasCreateDatasourcePermission( const canCreateActions = getHasCreateActionPermission(
isFeatureEnabled,
pagePermissions,
);
const canCreateDatasource = getHasCreateDatasourcePermission(
isFeatureEnabled,
userWorkspacePermissions, userWorkspacePermissions,
); );
@ -109,6 +117,7 @@ export const getFilteredAndSortedFileOperations = (
canCreateActions = true, canCreateActions = true,
canCreateDatasource = true, canCreateDatasource = true,
pagePermissions: string[] = [], pagePermissions: string[] = [],
isFeatureEnabled = false,
) => { ) => {
const fileOperations: ActionOperation[] = []; const fileOperations: ActionOperation[] = [];
if (!canCreateActions) return fileOperations; if (!canCreateActions) return fileOperations;
@ -118,7 +127,7 @@ export const getFilteredAndSortedFileOperations = (
// Add app datasources // Add app datasources
if (appWideDS.length > 0 || otherDS.length > 0) { if (appWideDS.length > 0 || otherDS.length > 0) {
const showCreateQuery = [...appWideDS, ...otherDS].some((ds: Datasource) => const showCreateQuery = [...appWideDS, ...otherDS].some((ds: Datasource) =>
hasCreateDatasourceActionPermission([ getHasCreateDatasourceActionPermission(isFeatureEnabled, [
...(ds.userPermissions ?? []), ...(ds.userPermissions ?? []),
...pagePermissions, ...pagePermissions,
]), ]),
@ -135,7 +144,7 @@ export const getFilteredAndSortedFileOperations = (
// get all datasources, app ds listed first // get all datasources, app ds listed first
const datasources = [...appWideDS, ...otherDS].filter((ds) => const datasources = [...appWideDS, ...otherDS].filter((ds) =>
hasCreateDatasourceActionPermission([ getHasCreateDatasourceActionPermission(isFeatureEnabled, [
...(ds.userPermissions ?? []), ...(ds.userPermissions ?? []),
...pagePermissions, ...pagePermissions,
]), ]),

View File

@ -45,10 +45,6 @@ import {
} from "@appsmith/selectors/entitiesSelector"; } from "@appsmith/selectors/entitiesSelector";
import { extractApiUrlPath } from "transformers/RestActionTransformer"; import { extractApiUrlPath } from "transformers/RestActionTransformer";
import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors"; import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors";
import {
hasCreateDatasourcePermission,
hasManageDatasourcePermission,
} from "@appsmith/utils/permissionHelpers";
import { Text } from "design-system"; import { Text } from "design-system";
import { TEMP_DATASOURCE_ID } from "constants/Datasource"; import { TEMP_DATASOURCE_ID } from "constants/Datasource";
import LazyCodeEditor from "components/editorComponents/LazyCodeEditor"; import LazyCodeEditor from "components/editorComponents/LazyCodeEditor";
@ -58,6 +54,12 @@ import { isEnvironmentValid } from "@appsmith/utils/Environments";
import { DEFAULT_DATASOURCE_NAME } from "constants/ApiEditorConstants/ApiEditorConstants"; import { DEFAULT_DATASOURCE_NAME } from "constants/ApiEditorConstants/ApiEditorConstants";
import { isString } from "lodash"; import { isString } from "lodash";
import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors";
import {
getHasCreateDatasourcePermission,
getHasManageDatasourcePermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
import { isGACEnabled } from "@appsmith/utils/planHelpers";
import { selectFeatureFlags } from "@appsmith/selectors/featureFlagsSelectors";
type ReduxStateProps = { type ReduxStateProps = {
workspaceId: string; workspaceId: string;
@ -70,6 +72,7 @@ type ReduxStateProps = {
actionName: string; actionName: string;
formName: string; formName: string;
userWorkspacePermissions: string[]; userWorkspacePermissions: string[];
isFeatureEnabled: boolean;
}; };
type ReduxDispatchProps = { type ReduxDispatchProps = {
@ -499,6 +502,7 @@ class EmbeddedDatasourcePathComponent extends React.Component<
datasource, datasource,
datasourceObject, datasourceObject,
input: { value }, input: { value },
isFeatureEnabled,
userWorkspacePermissions, userWorkspacePermissions,
} = this.props; } = this.props;
const datasourceUrl = get(datasource, "datasourceConfiguration.url", ""); const datasourceUrl = get(datasource, "datasourceConfiguration.url", "");
@ -508,16 +512,18 @@ class EmbeddedDatasourcePathComponent extends React.Component<
value: displayValue, value: displayValue,
onChange: this.handleOnChange, onChange: this.handleOnChange,
}; };
const shouldSave = datasource && !("id" in datasource); const shouldSave = datasource && !("id" in datasource);
const isGACFeatureEnabled = isFeatureEnabled;
const canCreateDatasource = hasCreateDatasourcePermission( const canCreateDatasource = getHasCreateDatasourcePermission(
isGACFeatureEnabled,
userWorkspacePermissions, userWorkspacePermissions,
); );
const datasourcePermissions = datasourceObject?.userPermissions || []; const datasourcePermissions = datasourceObject?.userPermissions || [];
const canManageDatasource = hasManageDatasourcePermission( const canManageDatasource = getHasManageDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );
@ -585,13 +591,20 @@ class EmbeddedDatasourcePathComponent extends React.Component<
const mapStateToProps = ( const mapStateToProps = (
state: AppState, state: AppState,
ownProps: { pluginId: string; actionName: string; formName: string }, ownProps: {
pluginId: string;
actionName: string;
formName: string;
isFeatureEnabled: boolean;
},
): ReduxStateProps => { ): ReduxStateProps => {
const apiFormValueSelector = formValueSelector(ownProps.formName); const apiFormValueSelector = formValueSelector(ownProps.formName);
const datasourceFromAction = apiFormValueSelector(state, "datasource"); const datasourceFromAction = apiFormValueSelector(state, "datasource");
let datasourceMerged = datasourceFromAction || {}; let datasourceMerged = datasourceFromAction || {};
let datasourceFromDataSourceList: Datasource | undefined; let datasourceFromDataSourceList: Datasource | undefined;
const currentEnvironment = getCurrentEnvironmentId(state); const currentEnvironment = getCurrentEnvironmentId(state);
const featureFlags = selectFeatureFlags(state);
const isFeatureEnabled = isGACEnabled(featureFlags);
// Todo: fix this properly later in #2164 // Todo: fix this properly later in #2164
if (datasourceFromAction && "id" in datasourceFromAction) { if (datasourceFromAction && "id" in datasourceFromAction) {
datasourceFromDataSourceList = getDatasource( datasourceFromDataSourceList = getDatasource(
@ -619,6 +632,7 @@ const mapStateToProps = (
formName: ownProps.formName, formName: ownProps.formName,
userWorkspacePermissions: userWorkspacePermissions:
getCurrentAppWorkspace(state)?.userPermissions ?? [], getCurrentAppWorkspace(state)?.userPermissions ?? [],
isFeatureEnabled: isFeatureEnabled,
}; };
}; };

View File

@ -0,0 +1 @@
export * from "ce/utils/BusinessFeatures/adminSettingsHelpers";

View File

@ -0,0 +1 @@
export * from "ce/utils/BusinessFeatures/permissionPageHelpers";

View File

@ -15,12 +15,14 @@ import { getCurrentUser } from "selectors/usersSelectors";
import BusinessTag from "components/BusinessTag"; import BusinessTag from "components/BusinessTag";
import EnterpriseTag from "components/EnterpriseTag"; import EnterpriseTag from "components/EnterpriseTag";
import { getTenantPermissions } from "@appsmith/selectors/tenantSelectors"; import { getTenantPermissions } from "@appsmith/selectors/tenantSelectors";
import { hasAuditLogsReadPermission } from "@appsmith/utils/permissionHelpers";
import { import {
getFilteredAclCategories, getFilteredAclCategories,
getFilteredGeneralCategories, getFilteredGeneralCategories,
getFilteredOtherCategories, getFilteredOtherCategories,
} from "@appsmith/utils/adminSettingsHelpers"; } from "@appsmith/utils/adminSettingsHelpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasAuditLogsReadPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
export const Wrapper = styled.div` export const Wrapper = styled.div`
flex-basis: ${(props) => props.theme.sidebarWidth}; flex-basis: ${(props) => props.theme.sidebarWidth};
@ -190,7 +192,11 @@ export default function LeftPane() {
const user = useSelector(getCurrentUser); const user = useSelector(getCurrentUser);
const isSuperUser = user?.isSuperUser; const isSuperUser = user?.isSuperUser;
const tenantPermissions = useSelector(getTenantPermissions); const tenantPermissions = useSelector(getTenantPermissions);
const isAuditLogsEnabled = hasAuditLogsReadPermission(tenantPermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const isAuditLogsEnabled = getHasAuditLogsReadPermission(
isFeatureEnabled,
tenantPermissions,
);
const filteredGeneralCategories = getFilteredGeneralCategories(categories); const filteredGeneralCategories = getFilteredGeneralCategories(categories);

View File

@ -3,13 +3,13 @@ import AdminConfig from "@appsmith/pages/AdminSettings/config";
import { Redirect, useParams } from "react-router"; import { Redirect, useParams } from "react-router";
import { SettingCategories } from "@appsmith/pages/AdminSettings/config/types"; import { SettingCategories } from "@appsmith/pages/AdminSettings/config/types";
import SettingsForm from "pages/AdminSettings/SettingsForm"; import SettingsForm from "pages/AdminSettings/SettingsForm";
import { import { getWrapperCategory } from "@appsmith/utils/adminSettingsHelpers";
getDefaultAdminSettingsPath,
getWrapperCategory,
} from "@appsmith/utils/adminSettingsHelpers";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { getCurrentUser } from "selectors/usersSelectors"; import { getCurrentUser } from "selectors/usersSelectors";
import { getTenantPermissions } from "@appsmith/selectors/tenantSelectors"; import { getTenantPermissions } from "@appsmith/selectors/tenantSelectors";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getAdminSettingsPath } from "@appsmith/utils/BusinessFeatures/adminSettingsHelpers";
const Main = () => { const Main = () => {
const params = useParams() as any; const params = useParams() as any;
@ -22,6 +22,7 @@ const Main = () => {
subCategory, subCategory,
category, category,
); );
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
if (!!wrapperCategory?.component) { if (!!wrapperCategory?.component) {
const { component: WrapperCategoryComponent } = wrapperCategory; const { component: WrapperCategoryComponent } = wrapperCategory;
@ -32,7 +33,11 @@ const Main = () => {
) { ) {
return ( return (
<Redirect <Redirect
to={getDefaultAdminSettingsPath({ isSuperUser, tenantPermissions })} to={getAdminSettingsPath(
isFeatureEnabled,
isSuperUser,
tenantPermissions,
)}
/> />
); );
} else { } else {

View File

@ -15,12 +15,14 @@ import {
} from "@appsmith/constants/messages"; } from "@appsmith/constants/messages";
import StoreAsDatasource from "components/editorComponents/StoreAsDatasource"; import StoreAsDatasource from "components/editorComponents/StoreAsDatasource";
import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors"; import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors";
import {
hasCreateDatasourcePermission,
hasManageDatasourcePermission,
} from "@appsmith/utils/permissionHelpers";
import { Icon, Text } from "design-system"; import { Icon, Text } from "design-system";
import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import {
getHasCreateDatasourcePermission,
getHasManageDatasourcePermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
interface ReduxStateProps { interface ReduxStateProps {
datasource: EmbeddedRestDatasource; datasource: EmbeddedRestDatasource;
} }
@ -96,13 +98,17 @@ function ApiAuthentication(props: Props): JSX.Element {
(state: AppState) => getCurrentAppWorkspace(state)?.userPermissions ?? [], (state: AppState) => getCurrentAppWorkspace(state)?.userPermissions ?? [],
); );
const canCreateDatasource = hasCreateDatasourcePermission( const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreateDatasource = getHasCreateDatasourcePermission(
isFeatureEnabled,
userWorkspacePermissions, userWorkspacePermissions,
); );
const datasourcePermissions = datasource?.userPermissions || []; const datasourcePermissions = datasource?.userPermissions || [];
const canManageDatasource = hasManageDatasourcePermission( const canManageDatasource = getHasManageDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );

View File

@ -48,17 +48,19 @@ import equal from "fast-deep-equal/es6";
import ApiAuthentication from "./ApiAuthentication"; import ApiAuthentication from "./ApiAuthentication";
import { replayHighlightClass } from "globalStyles/portals"; import { replayHighlightClass } from "globalStyles/portals";
import { getPlugin } from "@appsmith/selectors/entitiesSelector"; import { getPlugin } from "@appsmith/selectors/entitiesSelector";
import {
hasDeleteActionPermission,
hasExecuteActionPermission,
hasManageActionPermission,
} from "@appsmith/utils/permissionHelpers";
import { setApiPaneConfigSelectedTabIndex } from "actions/apiPaneActions"; import { setApiPaneConfigSelectedTabIndex } from "actions/apiPaneActions";
import type { AutoGeneratedHeader } from "./helpers"; import type { AutoGeneratedHeader } from "./helpers";
import { showDebuggerFlag } from "selectors/debuggerSelectors"; import { showDebuggerFlag } from "selectors/debuggerSelectors";
import { getApiPaneConfigSelectedTabIndex } from "selectors/apiPaneSelectors"; import { getApiPaneConfigSelectedTabIndex } from "selectors/apiPaneSelectors";
import { noop } from "lodash"; import { noop } from "lodash";
import { DEFAULT_DATASOURCE_NAME } from "constants/ApiEditorConstants/ApiEditorConstants"; import { DEFAULT_DATASOURCE_NAME } from "constants/ApiEditorConstants/ApiEditorConstants";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import {
getHasDeleteActionPermission,
getHasExecuteActionPermission,
getHasManageActionPermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const Form = styled.form` const Form = styled.form`
position: relative; position: relative;
@ -531,13 +533,17 @@ function CommonEditorForm(props: CommonFormPropsWithExtraParams) {
(action) => action.id === params.apiId || action.id === params.queryId, (action) => action.id === params.apiId || action.id === params.queryId,
); );
const { pageId } = useParams<ExplorerURLParams>(); const { pageId } = useParams<ExplorerURLParams>();
const isChangePermitted = hasManageActionPermission( const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const isChangePermitted = getHasManageActionPermission(
isFeatureEnabled,
currentActionConfig?.userPermissions, currentActionConfig?.userPermissions,
); );
const isExecutePermitted = hasExecuteActionPermission( const isExecutePermitted = getHasExecuteActionPermission(
isFeatureEnabled,
currentActionConfig?.userPermissions, currentActionConfig?.userPermissions,
); );
const isDeletePermitted = hasDeleteActionPermission( const isDeletePermitted = getHasDeleteActionPermission(
isFeatureEnabled,
currentActionConfig?.userPermissions, currentActionConfig?.userPermissions,
); );

View File

@ -16,7 +16,6 @@ import {
PAGE_SETTINGS_ACTION_NAME_CONFLICT_ERROR, PAGE_SETTINGS_ACTION_NAME_CONFLICT_ERROR,
} from "@appsmith/constants/messages"; } from "@appsmith/constants/messages";
import type { Page } from "@appsmith/constants/ReduxActionConstants"; import type { Page } from "@appsmith/constants/ReduxActionConstants";
import { hasManagePagePermission } from "@appsmith/utils/permissionHelpers";
import classNames from "classnames"; import classNames from "classnames";
import { Input, Switch } from "design-system"; import { Input, Switch } from "design-system";
import ManualUpgrades from "components/BottomBar/ManualUpgrades"; import ManualUpgrades from "components/BottomBar/ManualUpgrades";
@ -35,6 +34,9 @@ import { filterAccentedAndSpecialCharacters, getUrlPreview } from "../Utils";
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import { getUsedActionNames } from "selectors/actionSelectors"; import { getUsedActionNames } from "selectors/actionSelectors";
import { isNameValid, resolveAsSpaceChar } from "utils/helpers"; import { isNameValid, resolveAsSpaceChar } from "utils/helpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasManagePagePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const UrlPreviewWrapper = styled.div` const UrlPreviewWrapper = styled.div`
height: 52px; height: 52px;
@ -61,8 +63,10 @@ function PageSettings(props: { page: Page }) {
const appNeedsUpdate = applicationVersion < ApplicationVersion.SLUG_URL; const appNeedsUpdate = applicationVersion < ApplicationVersion.SLUG_URL;
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const [canManagePages, setCanManagePages] = useState( const [canManagePages, setCanManagePages] = useState(
hasManagePagePermission(page?.userPermissions || []), getHasManagePagePermission(isFeatureEnabled, page?.userPermissions || []),
); );
const [pageName, setPageName] = useState(page.pageName); const [pageName, setPageName] = useState(page.pageName);
@ -103,7 +107,9 @@ function PageSettings(props: { page: Page }) {
setCustomSlug(page.customSlug || ""); setCustomSlug(page.customSlug || "");
setIsShown(!!!page.isHidden); setIsShown(!!!page.isHidden);
setIsDefault(!!page.isDefault); setIsDefault(!!page.isDefault);
setCanManagePages(hasManagePagePermission(page?.userPermissions || [])); setCanManagePages(
getHasManagePagePermission(isFeatureEnabled, page?.userPermissions || []),
);
}, [page, page.pageName, page.customSlug, page.isHidden, page.isDefault]); }, [page, page.pageName, page.customSlug, page.isHidden, page.isDefault]);
useEffect(() => { useEffect(() => {
@ -279,7 +285,7 @@ function PageSettings(props: { page: Page }) {
</UrlPreviewWrapper> </UrlPreviewWrapper>
)} )}
<div className="flex justify-between content-center pb-2"> <div className="flex content-center justify-between pb-2">
<Switch <Switch
className="mb-0" className="mb-0"
id="t--page-settings-show-nav-control" id="t--page-settings-show-nav-control"
@ -299,7 +305,7 @@ function PageSettings(props: { page: Page }) {
</Switch> </Switch>
</div> </div>
<div className="flex justify-between content-center"> <div className="flex content-center justify-between">
<Switch <Switch
className="mb-0" className="mb-0"
id="t--page-settings-home-page-control" id="t--page-settings-home-page-control"

View File

@ -34,12 +34,14 @@ import type {
QueryTemplate, QueryTemplate,
} from "entities/Datasource"; } from "entities/Datasource";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors"; import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
import {
hasCreateDatasourceActionPermission,
hasCreatePagePermission,
} from "@appsmith/utils/permissionHelpers";
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import AnalyticsUtil from "utils/AnalyticsUtil"; import AnalyticsUtil from "utils/AnalyticsUtil";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import {
getHasCreateDatasourceActionPermission,
getHasCreatePagePermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const ViewModeSchemaContainer = styled.div` const ViewModeSchemaContainer = styled.div`
height: 100%; height: 100%;
@ -109,12 +111,18 @@ const DatasourceViewModeSchema = (props: Props) => {
const userAppPermissions = useSelector( const userAppPermissions = useSelector(
(state: AppState) => getCurrentApplication(state)?.userPermissions ?? [], (state: AppState) => getCurrentApplication(state)?.userPermissions ?? [],
); );
const canCreatePages = hasCreatePagePermission(userAppPermissions);
const canCreateDatasourceActions = hasCreateDatasourceActionPermission([ const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
...datasourcePermissions,
...pagePermissions, const canCreatePages = getHasCreatePagePermission(
]); isFeatureEnabled,
userAppPermissions,
);
const canCreateDatasourceActions = getHasCreateDatasourceActionPermission(
isFeatureEnabled,
[...datasourcePermissions, ...pagePermissions],
);
const applicationId: string = useSelector(getCurrentApplicationId); const applicationId: string = useSelector(getCurrentApplicationId);
const { pageId: currentPageId } = useParams<ExplorerURLParams>(); const { pageId: currentPageId } = useParams<ExplorerURLParams>();

View File

@ -38,8 +38,10 @@ import CopyToClipBoard from "components/designSystems/appsmith/CopyToClipBoard";
import { updateReplayEntity } from "actions/pageActions"; import { updateReplayEntity } from "actions/pageActions";
import { ENTITY_TYPE } from "entities/AppsmithConsole"; import { ENTITY_TYPE } from "entities/AppsmithConsole";
import { TEMP_DATASOURCE_ID } from "constants/Datasource"; import { TEMP_DATASOURCE_ID } from "constants/Datasource";
import { hasManageDatasourcePermission } from "@appsmith/utils/permissionHelpers";
import { Form } from "./DBForm"; import { Form } from "./DBForm";
import { selectFeatureFlagCheck } from "@appsmith/selectors/featureFlagsSelectors";
import { getHasManageDatasourcePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
interface DatasourceRestApiEditorProps { interface DatasourceRestApiEditorProps {
initializeReplayEntity: (id: string, data: any) => void; initializeReplayEntity: (id: string, data: any) => void;
@ -73,6 +75,7 @@ interface DatasourceRestApiEditorProps {
triggerSave?: boolean; triggerSave?: boolean;
datasourceDeleteTrigger: () => void; datasourceDeleteTrigger: () => void;
viewMode: boolean; viewMode: boolean;
isFeatureEnabled: boolean;
} }
type Props = DatasourceRestApiEditorProps & type Props = DatasourceRestApiEditorProps &
@ -189,9 +192,10 @@ class DatasourceRestAPIEditor extends React.Component<Props> {
}; };
validate = (): boolean => { validate = (): boolean => {
const { datasource, datasourceId, formData } = this.props; const { datasource, datasourceId, formData, isFeatureEnabled } = this.props;
const createMode = datasourceId === TEMP_DATASOURCE_ID; const createMode = datasourceId === TEMP_DATASOURCE_ID;
const canManageDatasource = hasManageDatasourcePermission( const canManageDatasource = getHasManageDatasourcePermission(
isFeatureEnabled,
datasource?.userPermissions || [], datasource?.userPermissions || [],
); );
if (!formData) return true; if (!formData) return true;
@ -1006,11 +1010,17 @@ const mapStateToProps = (state: AppState, props: any) => {
const { currentEnvironment, datasource, formName } = props; const { currentEnvironment, datasource, formName } = props;
const hintMessages = datasource && datasource.messages; const hintMessages = datasource && datasource.messages;
const isFeatureEnabled = selectFeatureFlagCheck(
state,
FEATURE_FLAG.license_gac_enabled,
);
return { return {
initialValues: datasourceToFormValues(datasource, currentEnvironment), initialValues: datasourceToFormValues(datasource, currentEnvironment),
formMeta: getFormMeta(formName)(state), formMeta: getFormMeta(formName)(state),
messages: hintMessages, messages: hintMessages,
datasourceName: datasource?.name ?? "", datasourceName: datasource?.name ?? "",
isFeatureEnabled,
}; };
}; };

View File

@ -15,7 +15,9 @@ import {
Text, Text,
} from "design-system"; } from "design-system";
import { TEMP_DATASOURCE_ID } from "constants/Datasource"; import { TEMP_DATASOURCE_ID } from "constants/Datasource";
import { hasManageDatasourcePermission } from "@appsmith/utils/permissionHelpers"; import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { getHasManageDatasourcePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
interface SaveOrDiscardModalProps { interface SaveOrDiscardModalProps {
isOpen: boolean; isOpen: boolean;
@ -39,7 +41,9 @@ function SaveOrDiscardDatasourceModal(props: SaveOrDiscardModalProps) {
} = props; } = props;
const createMode = datasourceId === TEMP_DATASOURCE_ID; const createMode = datasourceId === TEMP_DATASOURCE_ID;
const canManageDatasources = hasManageDatasourcePermission( const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canManageDatasources = getHasManageDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );
const disableSaveButton = !createMode && !canManageDatasources; const disableSaveButton = !createMode && !canManageDatasources;

View File

@ -59,11 +59,6 @@ import { isDatasourceInViewMode } from "selectors/ui";
import { getQueryParams } from "utils/URLUtils"; import { getQueryParams } from "utils/URLUtils";
import { TEMP_DATASOURCE_ID } from "constants/Datasource"; import { TEMP_DATASOURCE_ID } from "constants/Datasource";
import SaveOrDiscardDatasourceModal from "./SaveOrDiscardDatasourceModal"; import SaveOrDiscardDatasourceModal from "./SaveOrDiscardDatasourceModal";
import {
hasCreateDatasourceActionPermission,
hasDeleteDatasourcePermission,
hasManageDatasourcePermission,
} from "@appsmith/utils/permissionHelpers";
import { toast, Callout } from "design-system"; import { toast, Callout } from "design-system";
import styled from "styled-components"; import styled from "styled-components";
@ -104,6 +99,12 @@ import AnalyticsUtil from "utils/AnalyticsUtil";
import { DATASOURCES_ALLOWED_FOR_PREVIEW_MODE } from "constants/QueryEditorConstants"; import { DATASOURCES_ALLOWED_FOR_PREVIEW_MODE } from "constants/QueryEditorConstants";
import { setCurrentEditingEnvironmentID } from "@appsmith/actions/environmentAction"; import { setCurrentEditingEnvironmentID } from "@appsmith/actions/environmentAction";
import { getCurrentEnvironmentDetails } from "@appsmith/selectors/environmentSelectors"; import { getCurrentEnvironmentDetails } from "@appsmith/selectors/environmentSelectors";
import { isGACEnabled } from "@appsmith/utils/planHelpers";
import {
getHasCreateDatasourceActionPermission,
getHasDeleteDatasourcePermission,
getHasManageDatasourcePermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
interface ReduxStateProps { interface ReduxStateProps {
canCreateDatasourceActions: boolean; canCreateDatasourceActions: boolean;
@ -1038,19 +1039,24 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
const datasourcePermissions = datasource?.userPermissions || []; const datasourcePermissions = datasource?.userPermissions || [];
const canManageDatasource = hasManageDatasourcePermission( const featureFlags = selectFeatureFlags(state);
const isFeatureEnabled = isGACEnabled(featureFlags);
const canManageDatasource = getHasManageDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );
const canDeleteDatasource = hasDeleteDatasourcePermission( const canDeleteDatasource = getHasDeleteDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );
const pagePermissions = getPagePermissions(state); const pagePermissions = getPagePermissions(state);
const canCreateDatasourceActions = hasCreateDatasourceActionPermission([ const canCreateDatasourceActions = getHasCreateDatasourceActionPermission(
...datasourcePermissions, isFeatureEnabled,
...pagePermissions, [...datasourcePermissions, ...pagePermissions],
]); );
// Debugger render flag // Debugger render flag
const showDebugger = showDebuggerFlag(state); const showDebugger = showDebuggerFlag(state);
const pluginPackageName = plugin?.packageName ?? ""; const pluginPackageName = plugin?.packageName ?? "";
@ -1070,8 +1076,6 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
pluginId, pluginId,
); );
const featureFlags = selectFeatureFlags(state);
// A/B feature flag for datasource view mode preview data. // A/B feature flag for datasource view mode preview data.
let isEnabledForDSViewModeSchema = selectFeatureFlagCheck( let isEnabledForDSViewModeSchema = selectFeatureFlagCheck(
state, state,

View File

@ -19,11 +19,13 @@ import { keyBy } from "lodash";
import { getActionConfig } from "./helpers"; import { getActionConfig } from "./helpers";
import AnalyticsUtil from "utils/AnalyticsUtil"; import AnalyticsUtil from "utils/AnalyticsUtil";
import { useLocation } from "react-router"; import { useLocation } from "react-router";
import {
hasDeleteActionPermission,
hasManageActionPermission,
} from "@appsmith/utils/permissionHelpers";
import type { Datasource } from "entities/Datasource"; import type { Datasource } from "entities/Datasource";
import {
getHasDeleteActionPermission,
getHasManageActionPermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
const getUpdateActionNameReduxAction = (id: string, name: string) => { const getUpdateActionNameReduxAction = (id: string, name: string) => {
return saveActionName({ id, name }); return saveActionName({ id, name });
@ -78,9 +80,17 @@ export const ExplorerActionEntity = memo((props: ExplorerActionEntityProps) => {
const actionPermissions = action.userPermissions || []; const actionPermissions = action.userPermissions || [];
const canDeleteAction = hasDeleteActionPermission(actionPermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canManageAction = hasManageActionPermission(actionPermissions); const canDeleteAction = getHasDeleteActionPermission(
isFeatureEnabled,
actionPermissions,
);
const canManageAction = getHasManageActionPermission(
isFeatureEnabled,
actionPermissions,
);
const contextMenu = ( const contextMenu = (
<ActionEntityContextMenu <ActionEntityContextMenu

View File

@ -34,13 +34,15 @@ import { integrationEditorURL } from "RouteBuilder";
import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors"; import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors";
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import {
hasCreateDatasourcePermission,
hasManageDatasourcePermission,
} from "@appsmith/utils/permissionHelpers";
import { DatasourceCreateEntryPoints } from "constants/Datasource"; import { DatasourceCreateEntryPoints } from "constants/Datasource";
import AnalyticsUtil from "utils/AnalyticsUtil"; import AnalyticsUtil from "utils/AnalyticsUtil";
import WalkthroughContext from "components/featureWalkthrough/walkthroughContext"; import WalkthroughContext from "components/featureWalkthrough/walkthroughContext";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import {
getHasCreateDatasourcePermission,
getHasManageDatasourcePermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const ShowAllButton = styled(Button)` const ShowAllButton = styled(Button)`
margin: 0.25rem 1.5rem; margin: 0.25rem 1.5rem;
@ -60,7 +62,10 @@ const Datasources = React.memo(() => {
(state: AppState) => getCurrentAppWorkspace(state).userPermissions ?? [], (state: AppState) => getCurrentAppWorkspace(state).userPermissions ?? [],
); );
const canCreateDatasource = hasCreateDatasourcePermission( const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreateDatasource = getHasCreateDatasourcePermission(
isFeatureEnabled,
userWorkspacePermissions, userWorkspacePermissions,
); );
@ -100,7 +105,8 @@ const Datasources = React.memo(() => {
appWideDS.concat(datasourceSuggestions).map((datasource: Datasource) => { appWideDS.concat(datasourceSuggestions).map((datasource: Datasource) => {
const datasourcePermissions = datasource.userPermissions || []; const datasourcePermissions = datasource.userPermissions || [];
const canManageDatasource = hasManageDatasourcePermission( const canManageDatasource = getHasManageDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );
return ( return (

View File

@ -13,15 +13,17 @@ import {
createMessage, createMessage,
} from "@appsmith/constants/messages"; } from "@appsmith/constants/messages";
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import {
hasDeleteDatasourcePermission,
hasManageDatasourcePermission,
} from "@appsmith/utils/permissionHelpers";
import { getDatasource } from "@appsmith/selectors/entitiesSelector"; import { getDatasource } from "@appsmith/selectors/entitiesSelector";
import type { TreeDropdownOption } from "pages/Editor/Explorer/ContextMenu"; import type { TreeDropdownOption } from "pages/Editor/Explorer/ContextMenu";
import ContextMenu from "pages/Editor/Explorer/ContextMenu"; import ContextMenu from "pages/Editor/Explorer/ContextMenu";
import { DatasourceStructureContext } from "./DatasourceStructure"; import { DatasourceStructureContext } from "./DatasourceStructure";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import {
getHasDeleteDatasourcePermission,
getHasManageDatasourcePermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
export function DataSourceContextMenu(props: { export function DataSourceContextMenu(props: {
datasourceId: string; datasourceId: string;
@ -51,13 +53,17 @@ export function DataSourceContextMenu(props: {
getDatasource(state, props.datasourceId), getDatasource(state, props.datasourceId),
); );
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const datasourcePermissions = datasource?.userPermissions || []; const datasourcePermissions = datasource?.userPermissions || [];
const canDeleteDatasource = hasDeleteDatasourcePermission( const canDeleteDatasource = getHasDeleteDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );
const canManageDatasource = hasManageDatasourcePermission( const canManageDatasource = getHasManageDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );

View File

@ -6,7 +6,6 @@ import DatasourceField from "./DatasourceField";
import type { DatasourceTable } from "entities/Datasource"; import type { DatasourceTable } from "entities/Datasource";
import { useCloseMenuOnScroll } from "../hooks"; import { useCloseMenuOnScroll } from "../hooks";
import { SIDEBAR_ID } from "constants/Explorer"; import { SIDEBAR_ID } from "constants/Explorer";
import { hasCreateDatasourceActionPermission } from "@appsmith/utils/permissionHelpers";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import { getDatasource, getPlugin } from "@appsmith/selectors/entitiesSelector"; import { getDatasource, getPlugin } from "@appsmith/selectors/entitiesSelector";
@ -18,6 +17,9 @@ import AnalyticsUtil from "utils/AnalyticsUtil";
import type { Plugin } from "api/PluginApi"; import type { Plugin } from "api/PluginApi";
import { omit } from "lodash"; import { omit } from "lodash";
import { Virtuoso } from "react-virtuoso"; import { Virtuoso } from "react-virtuoso";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasCreateDatasourceActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
export enum DatasourceStructureContext { export enum DatasourceStructureContext {
EXPLORER = "entity-explorer", EXPLORER = "entity-explorer",
@ -67,11 +69,12 @@ const DatasourceStructureItem = memo((props: DatasourceStructureItemProps) => {
const datasourcePermissions = datasource?.userPermissions || []; const datasourcePermissions = datasource?.userPermissions || [];
const pagePermissions = useSelector(getPagePermissions); const pagePermissions = useSelector(getPagePermissions);
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreateDatasourceActions = hasCreateDatasourceActionPermission([ const canCreateDatasourceActions = getHasCreateDatasourceActionPermission(
...datasourcePermissions, isFeatureEnabled,
...pagePermissions, [...datasourcePermissions, ...pagePermissions],
]); );
const onSelect = () => { const onSelect = () => {
setActive(false); setActive(false);

View File

@ -14,7 +14,7 @@ import { mockDatasources } from "./mockTestData";
import { updateCurrentPage } from "actions/pageActions"; import { updateCurrentPage } from "actions/pageActions";
import urlBuilder from "entities/URLRedirect/URLAssembly"; import urlBuilder from "entities/URLRedirect/URLAssembly";
import * as helpers from "@appsmith/pages/Editor/Explorer/helpers"; import * as helpers from "@appsmith/pages/Editor/Explorer/helpers";
import * as permissionUtils from "@appsmith/utils/permissionHelpers"; import * as permissionPageHelpers from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
import * as widgetSelectionsActions from "actions/widgetSelectionActions"; import * as widgetSelectionsActions from "actions/widgetSelectionActions";
@ -40,6 +40,13 @@ jest.mock("@appsmith/pages/Editor/Explorer/helpers", () => ({
...jest.requireActual("@appsmith/pages/Editor/Explorer/helpers"), ...jest.requireActual("@appsmith/pages/Editor/Explorer/helpers"),
})); }));
jest.mock("@appsmith/utils/BusinessFeatures/permissionPageHelpers", () => ({
__esModule: true,
...jest.requireActual(
"@appsmith/utils/BusinessFeatures/permissionPageHelpers",
),
}));
describe("Entity Explorer tests", () => { describe("Entity Explorer tests", () => {
beforeAll(() => { beforeAll(() => {
runSagaMiddleware(); runSagaMiddleware();
@ -69,7 +76,7 @@ describe("Entity Explorer tests", () => {
payload: mockDatasources, payload: mockDatasources,
}); });
jest jest
.spyOn(permissionUtils, "hasCreateDatasourcePermission") .spyOn(permissionPageHelpers, "getHasCreateDatasourcePermission")
.mockReturnValue(true); .mockReturnValue(true);
store.dispatch(updateCurrentPage("pageId")); store.dispatch(updateCurrentPage("pageId"));
const component = render(<Datasources />); const component = render(<Datasources />);
@ -83,7 +90,7 @@ describe("Entity Explorer tests", () => {
payload: mockDatasources, payload: mockDatasources,
}); });
jest jest
.spyOn(permissionUtils, "hasCreateDatasourcePermission") .spyOn(permissionPageHelpers, "getHasCreateDatasourcePermission")
.mockReturnValue(false); .mockReturnValue(false);
const mockExplorerState = jest.spyOn(helpers, "getExplorerStatus"); const mockExplorerState = jest.spyOn(helpers, "getExplorerStatus");
mockExplorerState.mockImplementationOnce(() => true); mockExplorerState.mockImplementationOnce(() => true);
@ -103,13 +110,13 @@ describe("Entity Explorer tests", () => {
payload: mockDatasources, payload: mockDatasources,
}); });
jest jest
.spyOn(permissionUtils, "hasCreateDatasourcePermission") .spyOn(permissionPageHelpers, "getHasCreateDatasourcePermission")
.mockReturnValue(true); .mockReturnValue(true);
jest jest
.spyOn(permissionUtils, "hasManageDatasourcePermission") .spyOn(permissionPageHelpers, "getHasManageDatasourcePermission")
.mockReturnValue(false); .mockReturnValue(false);
jest jest
.spyOn(permissionUtils, "hasDeleteDatasourcePermission") .spyOn(permissionPageHelpers, "getHasDeleteDatasourcePermission")
.mockReturnValue(false); .mockReturnValue(false);
const mockExplorerState = jest.spyOn(helpers, "getExplorerStatus"); const mockExplorerState = jest.spyOn(helpers, "getExplorerStatus");
mockExplorerState.mockImplementationOnce(() => true); mockExplorerState.mockImplementationOnce(() => true);

View File

@ -22,7 +22,6 @@ import {
} from "@appsmith/constants/messages"; } from "@appsmith/constants/messages";
import { useCloseMenuOnScroll } from "../hooks"; import { useCloseMenuOnScroll } from "../hooks";
import { SIDEBAR_ID } from "constants/Explorer"; import { SIDEBAR_ID } from "constants/Explorer";
import { hasCreateActionPermission } from "@appsmith/utils/permissionHelpers";
import { import {
Menu, Menu,
MenuContent, MenuContent,
@ -33,6 +32,9 @@ import {
Text, Text,
} from "design-system"; } from "design-system";
import { DatasourceCreateEntryPoints } from "constants/Datasource"; import { DatasourceCreateEntryPoints } from "constants/Datasource";
import { getHasCreateActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
const SubMenuContainer = styled.div` const SubMenuContainer = styled.div`
width: 250px; width: 250px;
@ -73,7 +75,12 @@ export default function ExplorerSubMenu({
const pagePermissions = useSelector(getPagePermissions); const pagePermissions = useSelector(getPagePermissions);
const canCreateActions = hasCreateActionPermission(pagePermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreateActions = getHasCreateActionPermission(
isFeatureEnabled,
pagePermissions,
);
useEffect(() => { useEffect(() => {
setQuery(""); setQuery("");
@ -173,7 +180,7 @@ export default function ExplorerSubMenu({
key={`file-op-${idx}`} key={`file-op-${idx}`}
onClick={() => handleClick(item)} onClick={() => handleClick(item)}
> >
<div className="flex gap-2 items-center"> <div className="flex items-center gap-2">
{icon && <span className="flex-shrink-0">{icon}</span>} {icon && <span className="flex-shrink-0">{icon}</span>}
<span className="overflow-hidden whitespace-nowrap overflow-ellipsis"> <span className="overflow-hidden whitespace-nowrap overflow-ellipsis">
{item.shortTitle || item.title} {item.shortTitle || item.title}

View File

@ -22,9 +22,11 @@ import {
} from "@appsmith/pages/Editor/Explorer/helpers"; } from "@appsmith/pages/Editor/Explorer/helpers";
import { AddEntity, EmptyComponent } from "../common"; import { AddEntity, EmptyComponent } from "../common";
import ExplorerSubMenu from "./Submenu"; import ExplorerSubMenu from "./Submenu";
import { hasCreateActionPermission } from "@appsmith/utils/permissionHelpers";
import { Icon, Text } from "design-system"; import { Icon, Text } from "design-system";
import styled from "styled-components"; import styled from "styled-components";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasCreateActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const StyledText = styled(Text)` const StyledText = styled(Text)`
color: var(--ads-v2-color-fg-emphasis); color: var(--ads-v2-color-fg-emphasis);
@ -63,7 +65,12 @@ function Files() {
const pagePermissions = useSelector(getPagePermissions); const pagePermissions = useSelector(getPagePermissions);
const canCreateActions = hasCreateActionPermission(pagePermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreateActions = getHasCreateActionPermission(
isFeatureEnabled,
pagePermissions,
);
const onMenuClose = useCallback(() => openMenu(false), [openMenu]); const onMenuClose = useCallback(() => openMenu(false), [openMenu]);

View File

@ -14,9 +14,11 @@ import { jsCollectionIdURL } from "RouteBuilder";
import AnalyticsUtil from "utils/AnalyticsUtil"; import AnalyticsUtil from "utils/AnalyticsUtil";
import { useLocation } from "react-router"; import { useLocation } from "react-router";
import { import {
hasDeleteActionPermission, getHasDeleteActionPermission,
hasManageActionPermission, getHasManageActionPermission,
} from "@appsmith/utils/permissionHelpers"; } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
type ExplorerJSCollectionEntityProps = { type ExplorerJSCollectionEntityProps = {
step: number; step: number;
@ -58,9 +60,17 @@ export const ExplorerJSCollectionEntity = memo(
const jsActionPermissions = jsAction.userPermissions || []; const jsActionPermissions = jsAction.userPermissions || [];
const canDeleteJSAction = hasDeleteActionPermission(jsActionPermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canManageJSAction = hasManageActionPermission(jsActionPermissions); const canDeleteJSAction = getHasDeleteActionPermission(
isFeatureEnabled,
jsActionPermissions,
);
const canManageJSAction = getHasManageActionPermission(
isFeatureEnabled,
jsActionPermissions,
);
const contextMenu = ( const contextMenu = (
<JSCollectionEntityContextMenu <JSCollectionEntityContextMenu

View File

@ -38,11 +38,13 @@ import {
getCurrentPageId, getCurrentPageId,
getPagePermissions, getPagePermissions,
} from "selectors/editorSelectors"; } from "selectors/editorSelectors";
import { hasCreateActionPermission } from "@appsmith/utils/permissionHelpers";
import recommendedLibraries from "./recommendedLibraries"; import recommendedLibraries from "./recommendedLibraries";
import { useTransition, animated } from "react-spring"; import { useTransition, animated } from "react-spring";
import { isAirgapped } from "@appsmith/utils/airgapHelpers"; import { isAirgapped } from "@appsmith/utils/airgapHelpers";
import { Installer } from "./Installer"; import { Installer } from "./Installer";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasCreateActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const docsURLMap = recommendedLibraries.reduce((acc, lib) => { const docsURLMap = recommendedLibraries.reduce((acc, lib) => {
acc[lib.url] = lib.docsURL; acc[lib.url] = lib.docsURL;
@ -241,7 +243,7 @@ function LibraryEntity({ lib }: { lib: TJSLibrary }) {
name="right-arrow-2" name="right-arrow-2"
size={"md"} size={"md"}
/> />
<div className="flex items-center flex-start flex-1 overflow-hidden"> <div className="flex items-center flex-1 overflow-hidden flex-start">
<Name>{lib.name}</Name> <Name>{lib.name}</Name>
{docsURL && ( {docsURL && (
<div className="share"> <div className="share">
@ -262,7 +264,7 @@ function LibraryEntity({ lib }: { lib: TJSLibrary }) {
<PrimaryCTA lib={lib} /> <PrimaryCTA lib={lib} />
</div> </div>
<Collapse className="text-xs" isOpen={isOpen}> <Collapse className="text-xs" isOpen={isOpen}>
<div className="content pr-2"> <div className="pr-2 content">
Available as{" "} Available as{" "}
<div className="accessor"> <div className="accessor">
{lib.accessor[lib.accessor.length - 1]}{" "} {lib.accessor[lib.accessor.length - 1]}{" "}
@ -300,7 +302,12 @@ function JSDependencies() {
const pagePermissions = useSelector(getPagePermissions); const pagePermissions = useSelector(getPagePermissions);
const canCreateActions = hasCreateActionPermission(pagePermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreateActions = getHasCreateActionPermission(
isFeatureEnabled,
pagePermissions,
);
const isAirgappedInstance = isAirgapped(); const isAirgappedInstance = isAirgapped();

View File

@ -22,16 +22,18 @@ import {
} from "@appsmith/constants/messages"; } from "@appsmith/constants/messages";
import { openAppSettingsPaneAction } from "actions/appSettingsPaneActions"; import { openAppSettingsPaneAction } from "actions/appSettingsPaneActions";
import { AppSettingsTabs } from "pages/Editor/AppSettingsPane/AppSettings"; import { AppSettingsTabs } from "pages/Editor/AppSettingsPane/AppSettings";
import {
hasCreatePagePermission,
hasDeletePagePermission,
hasManagePagePermission,
} from "@appsmith/utils/permissionHelpers";
import { getPageById } from "selectors/editorSelectors"; import { getPageById } from "selectors/editorSelectors";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors"; import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import ContextMenu from "pages/Editor/Explorer/ContextMenu"; import ContextMenu from "pages/Editor/Explorer/ContextMenu";
import type { TreeDropdownOption } from "pages/Editor/Explorer/ContextMenu"; import type { TreeDropdownOption } from "pages/Editor/Explorer/ContextMenu";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import {
getHasCreatePagePermission,
getHasDeletePagePermission,
getHasManagePagePermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const CustomLabel = styled.div` const CustomLabel = styled.div`
display: flex; display: flex;
@ -123,11 +125,22 @@ export function PageContextMenu(props: {
(state: AppState) => getCurrentApplication(state)?.userPermissions ?? [], (state: AppState) => getCurrentApplication(state)?.userPermissions ?? [],
); );
const canCreatePages = hasCreatePagePermission(userAppPermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canManagePages = hasManagePagePermission(pagePermissions); const canCreatePages = getHasCreatePagePermission(
isFeatureEnabled,
userAppPermissions,
);
const canDeletePages = hasDeletePagePermission(pagePermissions); const canManagePages = getHasManagePagePermission(
isFeatureEnabled,
pagePermissions,
);
const canDeletePages = getHasDeletePagePermission(
isFeatureEnabled,
pagePermissions,
);
const optionsTree = [ const optionsTree = [
canManagePages && { canManagePages && {

View File

@ -36,13 +36,15 @@ import AddPageContextMenu from "./AddPageContextMenu";
import AnalyticsUtil from "utils/AnalyticsUtil"; import AnalyticsUtil from "utils/AnalyticsUtil";
import { useLocation } from "react-router"; import { useLocation } from "react-router";
import { toggleInOnboardingWidgetSelection } from "actions/onboardingActions"; import { toggleInOnboardingWidgetSelection } from "actions/onboardingActions";
import {
hasCreatePagePermission,
hasManagePagePermission,
} from "@appsmith/utils/permissionHelpers";
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors"; import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors";
import { getInstanceId } from "@appsmith//selectors/tenantSelectors"; import { getInstanceId } from "@appsmith//selectors/tenantSelectors";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import {
getHasCreatePagePermission,
getHasManagePagePermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const ENTITY_HEIGHT = 36; const ENTITY_HEIGHT = 36;
const MIN_PAGES_HEIGHT = 60; const MIN_PAGES_HEIGHT = 60;
@ -172,7 +174,12 @@ function Pages() {
(state: AppState) => getCurrentApplication(state)?.userPermissions ?? [], (state: AppState) => getCurrentApplication(state)?.userPermissions ?? [],
); );
const canCreatePages = hasCreatePagePermission(userAppPermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreatePages = getHasCreatePagePermission(
isFeatureEnabled,
userAppPermissions,
);
const pageElements = useMemo( const pageElements = useMemo(
() => () =>
@ -180,7 +187,10 @@ function Pages() {
const icon = page.isDefault ? defaultPageIcon : pageIcon; const icon = page.isDefault ? defaultPageIcon : pageIcon;
const isCurrentPage = currentPageId === page.pageId; const isCurrentPage = currentPageId === page.pageId;
const pagePermissions = page.userPermissions; const pagePermissions = page.userPermissions;
const canManagePages = hasManagePagePermission(pagePermissions); const canManagePages = getHasManagePagePermission(
isFeatureEnabled,
pagePermissions,
);
const contextMenu = ( const contextMenu = (
<PageContextMenu <PageContextMenu
applicationId={applicationId as string} applicationId={applicationId as string}
@ -223,7 +233,7 @@ function Pages() {
<StyledEntity <StyledEntity
addButtonHelptext={createMessage(ADD_PAGE_TOOLTIP)} addButtonHelptext={createMessage(ADD_PAGE_TOOLTIP)}
alwaysShowRightIcon alwaysShowRightIcon
className="group pages p-3 pb-0" className="p-3 pb-0 group pages"
collapseRef={pageResizeRef} collapseRef={pageResizeRef}
customAddButton={ customAddButton={
<AddPageContextMenu <AddPageContextMenu

View File

@ -12,10 +12,12 @@ import WidgetIcon from "./WidgetIcon";
import AnalyticsUtil from "utils/AnalyticsUtil"; import AnalyticsUtil from "utils/AnalyticsUtil";
import { builderURL } from "RouteBuilder"; import { builderURL } from "RouteBuilder";
import { useLocation } from "react-router"; import { useLocation } from "react-router";
import { hasManagePagePermission } from "@appsmith/utils/permissionHelpers";
import { getPagePermissions } from "selectors/editorSelectors"; import { getPagePermissions } from "selectors/editorSelectors";
import { NavigationMethod } from "utils/history"; import { NavigationMethod } from "utils/history";
import { getEntityExplorerWidgetsToExpand } from "selectors/widgetSelectors"; import { getEntityExplorerWidgetsToExpand } from "selectors/widgetSelectors";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasManagePagePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
export type WidgetTree = WidgetProps & { children?: WidgetTree[] }; export type WidgetTree = WidgetProps & { children?: WidgetTree[] };
@ -80,7 +82,12 @@ export const WidgetEntity = memo((props: WidgetEntityProps) => {
const pagePermissions = useSelector(getPagePermissions); const pagePermissions = useSelector(getPagePermissions);
const canManagePages = hasManagePagePermission(pagePermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canManagePages = getHasManagePagePermission(
isFeatureEnabled,
pagePermissions,
);
const { const {
isWidgetSelected, isWidgetSelected,

View File

@ -22,8 +22,10 @@ import {
} from "@appsmith/pages/Editor/Explorer/helpers"; } from "@appsmith/pages/Editor/Explorer/helpers";
import { AddEntity, EmptyComponent } from "../common"; import { AddEntity, EmptyComponent } from "../common";
import { noop } from "lodash"; import { noop } from "lodash";
import { hasManagePagePermission } from "@appsmith/utils/permissionHelpers";
import { Icon } from "design-system"; import { Icon } from "design-system";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasManagePagePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
type ExplorerWidgetGroupProps = { type ExplorerWidgetGroupProps = {
step: number; step: number;
@ -58,7 +60,12 @@ export const ExplorerWidgetGroup = memo((props: ExplorerWidgetGroupProps) => {
const pagePermissions = useSelector(getPagePermissions); const pagePermissions = useSelector(getPagePermissions);
const canManagePages = hasManagePagePermission(pagePermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canManagePages = getHasManagePagePermission(
isFeatureEnabled,
pagePermissions,
);
return ( return (
<Entity <Entity

View File

@ -59,12 +59,14 @@ import { getCurrentApplicationId } from "selectors/editorSelectors";
import { datasourcesEditorIdURL, integrationEditorURL } from "RouteBuilder"; import { datasourcesEditorIdURL, integrationEditorURL } from "RouteBuilder";
import { PluginPackageName } from "entities/Action"; import { PluginPackageName } from "entities/Action";
import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors"; import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors";
import { hasCreateDatasourcePermission } from "@appsmith/utils/permissionHelpers";
import { getPluginImages } from "@appsmith/selectors/entitiesSelector"; import { getPluginImages } from "@appsmith/selectors/entitiesSelector";
import { getAssetUrl } from "@appsmith/utils/airgapHelpers"; import { getAssetUrl } from "@appsmith/utils/airgapHelpers";
import { DatasourceCreateEntryPoints } from "constants/Datasource"; import { DatasourceCreateEntryPoints } from "constants/Datasource";
import { isGoogleSheetPluginDS } from "utils/editorContextUtils"; import { isGoogleSheetPluginDS } from "utils/editorContextUtils";
import equal from "fast-deep-equal"; import equal from "fast-deep-equal";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasCreateDatasourcePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
// ---------- Styles ---------- // ---------- Styles ----------
@ -398,7 +400,10 @@ function GeneratePageForm() {
[selectColumn], [selectColumn],
); );
const canCreateDatasource = hasCreateDatasourcePermission( const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreateDatasource = getHasCreateDatasourcePermission(
isFeatureEnabled,
workspace?.userPermissions || [], workspace?.userPermissions || [],
); );

View File

@ -12,8 +12,10 @@ import {
createMessage, createMessage,
EMPTY_ACTIVE_DATA_SOURCES, EMPTY_ACTIVE_DATA_SOURCES,
} from "@appsmith/constants/messages"; } from "@appsmith/constants/messages";
import { hasCreateDatasourcePermission } from "@appsmith/utils/permissionHelpers";
import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors"; import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasCreateDatasourcePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const QueryHomePage = styled.div` const QueryHomePage = styled.div`
${thinScrollbar}; ${thinScrollbar};
@ -62,7 +64,10 @@ function ActiveDataSources(props: ActiveDataSourcesProps) {
(state: AppState) => getCurrentAppWorkspace(state).userPermissions ?? [], (state: AppState) => getCurrentAppWorkspace(state).userPermissions ?? [],
); );
const canCreateDatasource = hasCreateDatasourcePermission( const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreateDatasource = getHasCreateDatasourcePermission(
isFeatureEnabled,
userWorkspacePermissions, userWorkspacePermissions,
); );

View File

@ -37,12 +37,6 @@ import {
getCurrentPageId, getCurrentPageId,
getPagePermissions, getPagePermissions,
} from "selectors/editorSelectors"; } from "selectors/editorSelectors";
import {
hasCreateDatasourceActionPermission,
hasCreatePagePermission,
hasDeleteDatasourcePermission,
hasManageDatasourcePermission,
} from "@appsmith/utils/permissionHelpers";
import { getAssetUrl } from "@appsmith/utils/airgapHelpers"; import { getAssetUrl } from "@appsmith/utils/airgapHelpers";
import { MenuWrapper, StyledMenu } from "components/utils/formComponents"; import { MenuWrapper, StyledMenu } from "components/utils/formComponents";
import { DatasourceEditEntryPoints } from "constants/Datasource"; import { DatasourceEditEntryPoints } from "constants/Datasource";
@ -53,6 +47,14 @@ import {
} from "@appsmith/utils/Environments"; } from "@appsmith/utils/Environments";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors"; import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import {
getHasCreateDatasourceActionPermission,
getHasCreatePagePermission,
getHasDeleteDatasourcePermission,
getHasManageDatasourcePermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const Wrapper = styled.div` const Wrapper = styled.div`
padding: 15px; padding: 15px;
@ -167,18 +169,26 @@ function DatasourceCard(props: DatasourceCardProps) {
const userAppPermissions = useSelector( const userAppPermissions = useSelector(
(state: AppState) => getCurrentApplication(state)?.userPermissions ?? [], (state: AppState) => getCurrentApplication(state)?.userPermissions ?? [],
); );
const canCreatePages = hasCreatePagePermission(userAppPermissions);
const canCreateDatasourceActions = hasCreateDatasourceActionPermission([ const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
...datasourcePermissions,
...pagePermissions,
]);
const canEditDatasource = hasManageDatasourcePermission( const canCreatePages = getHasCreatePagePermission(
isFeatureEnabled,
userAppPermissions,
);
const canCreateDatasourceActions = getHasCreateDatasourceActionPermission(
isFeatureEnabled,
[...datasourcePermissions, ...pagePermissions],
);
const canEditDatasource = getHasManageDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );
const canDeleteDatasource = hasDeleteDatasourcePermission( const canDeleteDatasource = getHasDeleteDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );

View File

@ -28,7 +28,6 @@ import { getCurrentApplicationId } from "selectors/editorSelectors";
import { integrationEditorURL } from "RouteBuilder"; import { integrationEditorURL } from "RouteBuilder";
import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors"; import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors";
import { hasCreateDatasourcePermission } from "@appsmith/utils/permissionHelpers";
import { Tab, TabPanel, Tabs, TabsList } from "design-system"; import { Tab, TabPanel, Tabs, TabsList } from "design-system";
import Debugger, { import Debugger, {
ResizerContentContainer, ResizerContentContainer,
@ -38,6 +37,9 @@ import { showDebuggerFlag } from "selectors/debuggerSelectors";
import AnalyticsUtil from "utils/AnalyticsUtil"; import AnalyticsUtil from "utils/AnalyticsUtil";
import { DatasourceCreateEntryPoints } from "constants/Datasource"; import { DatasourceCreateEntryPoints } from "constants/Datasource";
import { isAirgapped } from "@appsmith/utils/airgapHelpers"; import { isAirgapped } from "@appsmith/utils/airgapHelpers";
import { selectFeatureFlags } from "@appsmith/selectors/featureFlagsSelectors";
import { isGACEnabled } from "@appsmith/utils/planHelpers";
import { getHasCreateDatasourcePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const HeaderFlex = styled.div` const HeaderFlex = styled.div`
font-size: 20px; font-size: 20px;
@ -591,7 +593,11 @@ const mapStateToProps = (state: AppState) => {
const userWorkspacePermissions = const userWorkspacePermissions =
getCurrentAppWorkspace(state).userPermissions ?? []; getCurrentAppWorkspace(state).userPermissions ?? [];
const canCreateDatasource = hasCreateDatasourcePermission( const featureFlags = selectFeatureFlags(state);
const isFeatureEnabled = isGACEnabled(featureFlags);
const canCreateDatasource = getHasCreateDatasourcePermission(
isFeatureEnabled,
userWorkspacePermissions, userWorkspacePermissions,
); );
return { return {

View File

@ -53,11 +53,6 @@ import {
} from "./styledComponents"; } from "./styledComponents";
import { getJSPaneConfigSelectedTab } from "selectors/jsPaneSelectors"; import { getJSPaneConfigSelectedTab } from "selectors/jsPaneSelectors";
import type { EventLocation } from "@appsmith/utils/analyticsUtilTypes"; import type { EventLocation } from "@appsmith/utils/analyticsUtilTypes";
import {
hasDeleteActionPermission,
hasExecuteActionPermission,
hasManageActionPermission,
} from "@appsmith/utils/permissionHelpers";
import { import {
setCodeEditorCursorAction, setCodeEditorCursorAction,
setFocusableInputField, setFocusableInputField,
@ -69,6 +64,13 @@ import styled from "styled-components";
import { showDebuggerFlag } from "selectors/debuggerSelectors"; import { showDebuggerFlag } from "selectors/debuggerSelectors";
import { Tab, TabPanel, Tabs, TabsList } from "design-system"; import { Tab, TabPanel, Tabs, TabsList } from "design-system";
import { JSEditorTab } from "reducers/uiReducers/jsPaneReducer"; import { JSEditorTab } from "reducers/uiReducers/jsPaneReducer";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import {
getHasDeleteActionPermission,
getHasExecuteActionPermission,
getHasManageActionPermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
interface JSFormProps { interface JSFormProps {
jsCollection: JSCollection; jsCollection: JSCollection;
@ -162,13 +164,18 @@ function JSEditorForm({ jsCollection: currentJSCollection }: Props) {
} }
}, [hash]); }, [hash]);
const isChangePermitted = hasManageActionPermission( const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const isChangePermitted = getHasManageActionPermission(
isFeatureEnabled,
currentJSCollection?.userPermissions || [], currentJSCollection?.userPermissions || [],
); );
const isExecutePermitted = hasExecuteActionPermission( const isExecutePermitted = getHasExecuteActionPermission(
isFeatureEnabled,
currentJSCollection?.userPermissions || [], currentJSCollection?.userPermissions || [],
); );
const isDeletePermitted = hasDeleteActionPermission( const isDeletePermitted = getHasDeleteActionPermission(
isFeatureEnabled,
currentJSCollection?.userPermissions || [], currentJSCollection?.userPermissions || [],
); );

View File

@ -99,12 +99,6 @@ import {
ResponseTabErrorDefaultMessage, ResponseTabErrorDefaultMessage,
} from "components/editorComponents/ApiResponseView"; } from "components/editorComponents/ApiResponseView";
import { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig"; import { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig";
import {
hasCreateDatasourcePermission,
hasDeleteActionPermission,
hasExecuteActionPermission,
hasManageActionPermission,
} from "@appsmith/utils/permissionHelpers";
import { getQueryPaneConfigSelectedTabIndex } from "selectors/queryPaneSelectors"; import { getQueryPaneConfigSelectedTabIndex } from "selectors/queryPaneSelectors";
import { setQueryPaneConfigSelectedTabIndex } from "actions/queryPaneActions"; import { setQueryPaneConfigSelectedTabIndex } from "actions/queryPaneActions";
import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants"; import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants";
@ -136,6 +130,14 @@ import { editorSQLModes } from "components/editorComponents/CodeEditor/sql/confi
import { EditorFormSignPosting } from "@appsmith/components/editorComponents/EditorFormSignPosting"; import { EditorFormSignPosting } from "@appsmith/components/editorComponents/EditorFormSignPosting";
import { DatasourceStructureContext } from "../Explorer/Datasources/DatasourceStructure"; import { DatasourceStructureContext } from "../Explorer/Datasources/DatasourceStructure";
import { selectFeatureFlags } from "@appsmith/selectors/featureFlagsSelectors"; import { selectFeatureFlags } from "@appsmith/selectors/featureFlagsSelectors";
import {
getHasCreateDatasourcePermission,
getHasDeleteActionPermission,
getHasExecuteActionPermission,
getHasManageActionPermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
const QueryFormContainer = styled.form` const QueryFormContainer = styled.form`
flex: 1; flex: 1;
@ -420,13 +422,19 @@ export function EditorJSONtoForm(props: Props) {
(action) => action.id === params.apiId || action.id === params.queryId, (action) => action.id === params.apiId || action.id === params.queryId,
); );
const { pageId } = useParams<ExplorerURLParams>(); const { pageId } = useParams<ExplorerURLParams>();
const isChangePermitted = hasManageActionPermission(
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const isChangePermitted = getHasManageActionPermission(
isFeatureEnabled,
currentActionConfig?.userPermissions, currentActionConfig?.userPermissions,
); );
const isExecutePermitted = hasExecuteActionPermission( const isExecutePermitted = getHasExecuteActionPermission(
isFeatureEnabled,
currentActionConfig?.userPermissions, currentActionConfig?.userPermissions,
); );
const isDeletePermitted = hasDeleteActionPermission( const isDeletePermitted = getHasDeleteActionPermission(
isFeatureEnabled,
currentActionConfig?.userPermissions, currentActionConfig?.userPermissions,
); );
@ -434,7 +442,8 @@ export function EditorJSONtoForm(props: Props) {
(state: AppState) => getCurrentAppWorkspace(state).userPermissions ?? [], (state: AppState) => getCurrentAppWorkspace(state).userPermissions ?? [],
); );
const canCreateDatasource = hasCreateDatasourcePermission( const canCreateDatasource = getHasCreateDatasourcePermission(
isFeatureEnabled,
userWorkspacePermissions, userWorkspacePermissions,
); );

View File

@ -45,11 +45,6 @@ import {
import type { PluginType } from "entities/Action"; import type { PluginType } from "entities/Action";
import AuthMessage from "pages/common/datasourceAuth/AuthMessage"; import AuthMessage from "pages/common/datasourceAuth/AuthMessage";
import { isDatasourceInViewMode } from "selectors/ui"; import { isDatasourceInViewMode } from "selectors/ui";
import {
hasCreateDatasourceActionPermission,
hasDeleteDatasourcePermission,
hasManageDatasourcePermission,
} from "@appsmith/utils/permissionHelpers";
import { TEMP_DATASOURCE_ID } from "constants/Datasource"; import { TEMP_DATASOURCE_ID } from "constants/Datasource";
import { import {
createTempDatasourceFromForm, createTempDatasourceFromForm,
@ -87,6 +82,13 @@ import GoogleSheetSchema from "./GoogleSheetSchema";
import AnalyticsUtil from "utils/AnalyticsUtil"; import AnalyticsUtil from "utils/AnalyticsUtil";
import { getDefaultEnvironmentId } from "@appsmith/selectors/environmentSelectors"; import { getDefaultEnvironmentId } from "@appsmith/selectors/environmentSelectors";
import { DEFAULT_ENV_ID } from "@appsmith/api/ApiUtils"; import { DEFAULT_ENV_ID } from "@appsmith/api/ApiUtils";
import {
getHasCreateDatasourceActionPermission,
getHasDeleteDatasourcePermission,
getHasManageDatasourcePermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
import { selectFeatureFlagCheck } from "@appsmith/selectors/featureFlagsSelectors";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
const ViewModeContainer = styled.div` const ViewModeContainer = styled.div`
display: flex; display: flex;
@ -707,19 +709,26 @@ const mapStateToProps = (state: AppState, props: any) => {
const datasourcePermissions = datasource?.userPermissions || []; const datasourcePermissions = datasource?.userPermissions || [];
const canManageDatasource = hasManageDatasourcePermission( const isFeatureEnabled = selectFeatureFlagCheck(
state,
FEATURE_FLAG.license_gac_enabled,
);
const canManageDatasource = getHasManageDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );
const canDeleteDatasource = hasDeleteDatasourcePermission( const canDeleteDatasource = getHasDeleteDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );
const pagePermissions = getPagePermissions(state); const pagePermissions = getPagePermissions(state);
const canCreateDatasourceActions = hasCreateDatasourceActionPermission([ const canCreateDatasourceActions = getHasCreateDatasourceActionPermission(
...datasourcePermissions, isFeatureEnabled,
...pagePermissions, [...datasourcePermissions, ...pagePermissions],
]); );
const gsheetToken = getGsheetToken(state); const gsheetToken = getGsheetToken(state);
const gsheetProjectID = getGsheetProjectID(state); const gsheetProjectID = getGsheetProjectID(state);

View File

@ -32,13 +32,15 @@ import {
GSHEETS_SCHEMA_NO_DATA, GSHEETS_SCHEMA_NO_DATA,
} from "@appsmith/constants/messages"; } from "@appsmith/constants/messages";
import AnalyticsUtil from "utils/AnalyticsUtil"; import AnalyticsUtil from "utils/AnalyticsUtil";
import {
hasCreateDatasourceActionPermission,
hasCreatePagePermission,
} from "@appsmith/utils/permissionHelpers";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors"; import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import { getDatasource } from "@appsmith/selectors/entitiesSelector"; import { getDatasource } from "@appsmith/selectors/entitiesSelector";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import {
getHasCreateDatasourceActionPermission,
getHasCreatePagePermission,
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
export const MessageWrapper = styled.div` export const MessageWrapper = styled.div`
display: flex; display: flex;
@ -287,12 +289,18 @@ function GoogleSheetSchema(props: Props) {
const userAppPermissions = useSelector( const userAppPermissions = useSelector(
(state: AppState) => getCurrentApplication(state)?.userPermissions ?? [], (state: AppState) => getCurrentApplication(state)?.userPermissions ?? [],
); );
const canCreatePages = hasCreatePagePermission(userAppPermissions);
const canCreateDatasourceActions = hasCreateDatasourceActionPermission([ const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
...datasourcePermissions,
...pagePermissions, const canCreatePages = getHasCreatePagePermission(
]); isFeatureEnabled,
userAppPermissions,
);
const canCreateDatasourceActions = getHasCreateDatasourceActionPermission(
isFeatureEnabled,
[...datasourcePermissions, ...pagePermissions],
);
const showGeneratePageBtn = const showGeneratePageBtn =
!isLoading && !isLoading &&

View File

@ -21,14 +21,16 @@ import {
getOnSelectAction, getOnSelectAction,
} from "pages/common/CustomizedDropdown/dropdownHelpers"; } from "pages/common/CustomizedDropdown/dropdownHelpers";
import { getCurrentUser } from "selectors/usersSelectors"; import { getCurrentUser } from "selectors/usersSelectors";
import {
getDefaultAdminSettingsPath,
showAdminSettings,
} from "@appsmith/utils/adminSettingsHelpers";
import { getTenantPermissions } from "@appsmith/selectors/tenantSelectors"; import { getTenantPermissions } from "@appsmith/selectors/tenantSelectors";
import { isAirgapped } from "@appsmith/utils/airgapHelpers"; import { isAirgapped } from "@appsmith/utils/airgapHelpers";
import { ShowUpgradeMenuItem } from "@appsmith/utils/licenseHelpers"; import { ShowUpgradeMenuItem } from "@appsmith/utils/licenseHelpers";
import { DISCORD_URL, DOCS_BASE_URL } from "constants/ThirdPartyConstants"; import { DISCORD_URL, DOCS_BASE_URL } from "constants/ThirdPartyConstants";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import {
getAdminSettingsPath,
getShowAdminSettings,
} from "@appsmith/utils/BusinessFeatures/adminSettingsHelpers";
export const Wrapper = styled.div` export const Wrapper = styled.div`
background-color: var(--ads-v2-color-bg); background-color: var(--ads-v2-color-bg);
@ -84,26 +86,29 @@ function LeftPaneBottomSection() {
const [isProductUpdatesModalOpen, setIsProductUpdatesModalOpen] = const [isProductUpdatesModalOpen, setIsProductUpdatesModalOpen] =
useState(false); useState(false);
const isAirgappedInstance = isAirgapped(); const isAirgappedInstance = isAirgapped();
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
return ( return (
<Wrapper> <Wrapper>
<MenuWrapper> <MenuWrapper>
<ShowUpgradeMenuItem /> <ShowUpgradeMenuItem />
{showAdminSettings(user) && !isFetchingApplications && ( {getShowAdminSettings(isFeatureEnabled, user) &&
<MenuItem !isFetchingApplications && (
className="admin-settings-menu-option" <MenuItem
icon="setting" className="admin-settings-menu-option"
onSelect={() => { icon="setting"
getOnSelectAction(DropdownOnSelectActions.REDIRECT, { onSelect={() => {
path: getDefaultAdminSettingsPath({ getOnSelectAction(DropdownOnSelectActions.REDIRECT, {
isSuperUser: user?.isSuperUser, path: getAdminSettingsPath(
tenantPermissions, isFeatureEnabled,
}), user?.isSuperUser,
}); tenantPermissions,
}} ),
text={createMessage(ADMIN_SETTINGS)} });
/> }}
)} text={createMessage(ADMIN_SETTINGS)}
/>
)}
{!isAirgappedInstance && ( {!isAirgappedInstance && (
<> <>
<MenuItem <MenuItem

View File

@ -19,9 +19,11 @@ import {
} from "@appsmith/constants/messages"; } from "@appsmith/constants/messages";
import { getAppsmithConfigs } from "@appsmith/configs"; import { getAppsmithConfigs } from "@appsmith/configs";
import { howMuchTimeBeforeText } from "utils/helpers"; import { howMuchTimeBeforeText } from "utils/helpers";
import { getDefaultAdminSettingsPath } from "@appsmith/utils/adminSettingsHelpers";
import { getTenantPermissions } from "@appsmith/selectors/tenantSelectors"; import { getTenantPermissions } from "@appsmith/selectors/tenantSelectors";
import { DISCORD_URL } from "constants/ThirdPartyConstants"; import { DISCORD_URL } from "constants/ThirdPartyConstants";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getAdminSettingsPath } from "@appsmith/utils/BusinessFeatures/adminSettingsHelpers";
type MobileSideBarProps = { type MobileSideBarProps = {
name: string; name: string;
@ -86,6 +88,7 @@ export default function MobileSideBar(props: MobileSideBarProps) {
const tenantPermissions = useSelector(getTenantPermissions); const tenantPermissions = useSelector(getTenantPermissions);
const { appVersion, cloudHosting } = getAppsmithConfigs(); const { appVersion, cloudHosting } = getAppsmithConfigs();
const howMuchTimeBefore = howMuchTimeBeforeText(appVersion.releaseDate); const howMuchTimeBefore = howMuchTimeBeforeText(appVersion.releaseDate);
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
return ( return (
<MainContainer isOpen={props.isOpen}> <MainContainer isOpen={props.isOpen}>
@ -110,10 +113,11 @@ export default function MobileSideBar(props: MobileSideBarProps) {
icon="setting" icon="setting"
onSelect={() => { onSelect={() => {
getOnSelectAction(DropdownOnSelectActions.REDIRECT, { getOnSelectAction(DropdownOnSelectActions.REDIRECT, {
path: getDefaultAdminSettingsPath({ path: getAdminSettingsPath(
isSuperUser: user?.isSuperUser, isFeatureEnabled,
user?.isSuperUser,
tenantPermissions, tenantPermissions,
}), ),
}); });
}} }}
text={createMessage(ADMIN_SETTINGS)} text={createMessage(ADMIN_SETTINGS)}

View File

@ -29,14 +29,15 @@ import {
import { Button, toast } from "design-system"; import { Button, toast } from "design-system";
import type { ApiDatasourceForm } from "entities/Datasource/RestAPIForm"; import type { ApiDatasourceForm } from "entities/Datasource/RestAPIForm";
import { TEMP_DATASOURCE_ID } from "constants/Datasource"; import { TEMP_DATASOURCE_ID } from "constants/Datasource";
import { hasManageDatasourcePermission } from "@appsmith/utils/permissionHelpers";
import { INTEGRATION_TABS, SHOW_FILE_PICKER_KEY } from "constants/routes"; import { INTEGRATION_TABS, SHOW_FILE_PICKER_KEY } from "constants/routes";
import { integrationEditorURL } from "RouteBuilder"; import { integrationEditorURL } from "RouteBuilder";
import { getQueryParams } from "utils/URLUtils"; import { getQueryParams } from "utils/URLUtils";
import type { AppsmithLocationState } from "utils/history"; import type { AppsmithLocationState } from "utils/history";
import type { PluginType } from "entities/Action"; import type { PluginType } from "entities/Action";
import { getCurrentEnvironmentDetails } from "@appsmith/selectors/environmentSelectors"; import { getCurrentEnvironmentDetails } from "@appsmith/selectors/environmentSelectors";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasManageDatasourcePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
interface Props { interface Props {
datasource: Datasource; datasource: Datasource;
@ -161,7 +162,10 @@ function DatasourceAuth({
const datasourcePermissions = datasource.userPermissions || []; const datasourcePermissions = datasource.userPermissions || [];
const canManageDatasource = hasManageDatasourcePermission( const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canManageDatasource = getHasManageDatasourcePermission(
isFeatureEnabled,
datasourcePermissions, datasourcePermissions,
); );

View File

@ -78,7 +78,6 @@ import {
} from "RouteBuilder"; } from "RouteBuilder";
import { getCurrentPageId } from "selectors/editorSelectors"; import { getCurrentPageId } from "selectors/editorSelectors";
import { validateResponse } from "./ErrorSagas"; import { validateResponse } from "./ErrorSagas";
import { hasManageActionPermission } from "@appsmith/utils/permissionHelpers";
import type { CreateDatasourceSuccessAction } from "actions/datasourceActions"; import type { CreateDatasourceSuccessAction } from "actions/datasourceActions";
import { removeTempDatasource } from "actions/datasourceActions"; import { removeTempDatasource } from "actions/datasourceActions";
import { klona } from "klona/lite"; import { klona } from "klona/lite";
@ -86,6 +85,10 @@ import { toast } from "design-system";
import type { AutoGeneratedHeader } from "pages/Editor/APIEditor/helpers"; import type { AutoGeneratedHeader } from "pages/Editor/APIEditor/helpers";
import { deriveAutoGeneratedHeaderState } from "pages/Editor/APIEditor/helpers"; import { deriveAutoGeneratedHeaderState } from "pages/Editor/APIEditor/helpers";
import { TEMP_DATASOURCE_ID } from "constants/Datasource"; import { TEMP_DATASOURCE_ID } from "constants/Datasource";
import type { FeatureFlags } from "@appsmith/entities/FeatureFlag";
import { selectFeatureFlags } from "@appsmith/selectors/featureFlagsSelectors";
import { isGACEnabled } from "@appsmith/utils/planHelpers";
import { getHasManageActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
function* syncApiParamsSaga( function* syncApiParamsSaga(
actionPayload: ReduxActionWithMeta<string, { field: string }>, actionPayload: ReduxActionWithMeta<string, { field: string }>,
@ -393,8 +396,14 @@ function* formValueChangeSaga(
if (form !== API_EDITOR_FORM_NAME) return; if (form !== API_EDITOR_FORM_NAME) return;
if (field === "dynamicBindingPathList" || field === "name") return; if (field === "dynamicBindingPathList" || field === "name") return;
const { values } = yield select(getFormData, API_EDITOR_FORM_NAME); const { values } = yield select(getFormData, API_EDITOR_FORM_NAME);
const featureFlags: FeatureFlags = yield select(selectFeatureFlags);
const isFeatureEnabled = isGACEnabled(featureFlags);
if (!values.id) return; if (!values.id) return;
if (!hasManageActionPermission(values.userPermissions)) {
if (
!getHasManageActionPermission(isFeatureEnabled, values.userPermissions)
) {
yield validateResponse({ yield validateResponse({
status: 403, status: 403,
resourceType: values?.pluginType, resourceType: values?.pluginType,

View File

@ -128,7 +128,6 @@ import WidgetFactory from "WidgetProvider/factory";
import { toggleShowDeviationDialog } from "actions/onboardingActions"; import { toggleShowDeviationDialog } from "actions/onboardingActions";
import { builderURL } from "RouteBuilder"; import { builderURL } from "RouteBuilder";
import { failFastApiCalls, waitForWidgetConfigBuild } from "./InitSagas"; import { failFastApiCalls, waitForWidgetConfigBuild } from "./InitSagas";
import { hasManagePagePermission } from "@appsmith/utils/permissionHelpers";
import { resizePublishedMainCanvasToLowestWidget } from "./WidgetOperationUtils"; import { resizePublishedMainCanvasToLowestWidget } from "./WidgetOperationUtils";
import { checkAndLogErrorsIfCyclicDependency } from "./helper"; import { checkAndLogErrorsIfCyclicDependency } from "./helper";
import { LOCAL_STORAGE_KEYS } from "utils/localStorage"; import { LOCAL_STORAGE_KEYS } from "utils/localStorage";
@ -147,6 +146,10 @@ import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
import type { WidgetProps } from "widgets/BaseWidget"; import type { WidgetProps } from "widgets/BaseWidget";
import { nestDSL, flattenDSL } from "@shared/dsl"; import { nestDSL, flattenDSL } from "@shared/dsl";
import { fetchSnapshotDetailsAction } from "actions/autoLayoutActions"; import { fetchSnapshotDetailsAction } from "actions/autoLayoutActions";
import { selectFeatureFlags } from "@appsmith/selectors/featureFlagsSelectors";
import type { FeatureFlags } from "@appsmith/entities/FeatureFlag";
import { isGACEnabled } from "@appsmith/utils/planHelpers";
import { getHasManagePagePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const WidgetTypes = WidgetFactory.widgetTypes; const WidgetTypes = WidgetFactory.widgetTypes;
@ -667,8 +670,14 @@ export function* saveLayoutSaga(action: ReduxAction<{ isRetry?: boolean }>) {
const appMode: APP_MODE | undefined = yield select(getAppMode); const appMode: APP_MODE | undefined = yield select(getAppMode);
const featureFlags: FeatureFlags = yield select(selectFeatureFlags);
const isFeatureEnabled = isGACEnabled(featureFlags);
if ( if (
!hasManagePagePermission(currentPage?.userPermissions || []) && !getHasManagePagePermission(
isFeatureEnabled,
currentPage?.userPermissions || [],
) &&
appMode === APP_MODE.EDIT appMode === APP_MODE.EDIT
) { ) {
yield validateResponse({ yield validateResponse({

View File

@ -76,13 +76,16 @@ import { FormDataPaths } from "workers/Evaluation/formEval";
import { fetchDynamicValuesSaga } from "./FormEvaluationSaga"; import { fetchDynamicValuesSaga } from "./FormEvaluationSaga";
import type { FormEvalOutput } from "reducers/evaluationReducers/formEvaluationReducer"; import type { FormEvalOutput } from "reducers/evaluationReducers/formEvaluationReducer";
import { validateResponse } from "./ErrorSagas"; import { validateResponse } from "./ErrorSagas";
import { hasManageActionPermission } from "@appsmith/utils/permissionHelpers";
import { getIsGeneratePageInitiator } from "utils/GenerateCrudUtil"; import { getIsGeneratePageInitiator } from "utils/GenerateCrudUtil";
import { toast } from "design-system"; import { toast } from "design-system";
import type { CreateDatasourceSuccessAction } from "actions/datasourceActions"; import type { CreateDatasourceSuccessAction } from "actions/datasourceActions";
import { createDefaultActionPayload } from "./ActionSagas"; import { createDefaultActionPayload } from "./ActionSagas";
import { DB_NOT_SUPPORTED } from "@appsmith/utils/Environments"; import { DB_NOT_SUPPORTED } from "@appsmith/utils/Environments";
import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors";
import type { FeatureFlags } from "@appsmith/entities/FeatureFlag";
import { selectFeatureFlags } from "@appsmith/selectors/featureFlagsSelectors";
import { isGACEnabled } from "@appsmith/utils/planHelpers";
import { getHasManageActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
// Called whenever the query being edited is changed via the URL or query pane // Called whenever the query being edited is changed via the URL or query pane
function* changeQuerySaga(actionPayload: ReduxAction<{ id: string }>) { function* changeQuerySaga(actionPayload: ReduxAction<{ id: string }>) {
@ -175,7 +178,12 @@ function* formValueChangeSaga(
const { values } = yield select(getFormData, QUERY_EDITOR_FORM_NAME); const { values } = yield select(getFormData, QUERY_EDITOR_FORM_NAME);
const hasRouteChanged = field === "id"; const hasRouteChanged = field === "id";
if (!hasManageActionPermission(values.userPermissions)) { const featureFlags: FeatureFlags = yield select(selectFeatureFlags);
const isFeatureEnabled = isGACEnabled(featureFlags);
if (
!getHasManageActionPermission(isFeatureEnabled, values.userPermissions)
) {
yield validateResponse({ yield validateResponse({
status: 403, status: 403,
resourceType: values?.pluginType, resourceType: values?.pluginType,