diff --git a/packages/manager/.changeset/pr-11137-fixed-1729745562099.md b/packages/manager/.changeset/pr-11137-fixed-1729745562099.md
new file mode 100644
index 00000000000..a502521a780
--- /dev/null
+++ b/packages/manager/.changeset/pr-11137-fixed-1729745562099.md
@@ -0,0 +1,5 @@
+---
+"@linode/manager": Fixed
+---
+
+Database create page form being enabled for restricted users ([#11137](https://github.com/linode/manager/pull/11137))
diff --git a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.test.tsx b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.test.tsx
index 40b0bf1c6ce..1b4c8241343 100644
--- a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.test.tsx
+++ b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.test.tsx
@@ -12,6 +12,18 @@ import DatabaseCreate from './DatabaseCreate';
const loadingTestId = 'circle-progress';
+const queryMocks = vi.hoisted(() => ({
+ useProfile: vi.fn().mockReturnValue({ data: { restricted: false } }),
+}));
+
+vi.mock('src/queries/profile/profile', async () => {
+ const actual = await vi.importActual('src/queries/profile/profile');
+ return {
+ ...actual,
+ useProfile: queryMocks.useProfile,
+ };
+});
+
beforeAll(() => mockMatchMedia());
describe('Database Create', () => {
@@ -154,4 +166,96 @@ describe('Database Create', () => {
expect(nodeRadioBtns).toHaveTextContent('$100/month $0.15/hr');
expect(nodeRadioBtns).toHaveTextContent('$140/month $0.21/hr');
});
+
+ it('should have the "Create Database Cluster" button disabled for restricted users', async () => {
+ queryMocks.useProfile.mockReturnValue({ data: { restricted: true } });
+
+ const { findByText, getByTestId } = renderWithTheme();
+
+ expect(getByTestId(loadingTestId)).toBeInTheDocument();
+
+ await waitForElementToBeRemoved(getByTestId(loadingTestId));
+ const createClusterButtonSpan = await findByText('Create Database Cluster');
+ const createClusterButton = createClusterButtonSpan.closest('button');
+
+ expect(createClusterButton).toBeInTheDocument();
+ expect(createClusterButton).toBeDisabled();
+ });
+
+ it('should disable form inputs for restricted users', async () => {
+ queryMocks.useProfile.mockReturnValue({ data: { restricted: true } });
+
+ const {
+ findAllByRole,
+ findAllByTestId,
+ findByPlaceholderText,
+ getByTestId,
+ } = renderWithTheme();
+
+ expect(getByTestId(loadingTestId)).toBeInTheDocument();
+
+ await waitForElementToBeRemoved(getByTestId(loadingTestId));
+ const textInputs = await findAllByTestId('textfield-input');
+ textInputs.forEach((input: HTMLInputElement) => {
+ expect(input).toBeDisabled();
+ });
+
+ const dbEngineSelect = await findByPlaceholderText(
+ 'Select a Database Engine'
+ );
+ expect(dbEngineSelect).toBeDisabled();
+ const regionSelect = await findByPlaceholderText('Select a Region');
+ expect(regionSelect).toBeDisabled();
+
+ const radioButtons = await findAllByRole('radio');
+ radioButtons.forEach((radioButton: HTMLElement) => {
+ expect(radioButton).toBeDisabled();
+ });
+ });
+
+ it('should have the "Create Database Cluster" button enabled for users with full access', async () => {
+ queryMocks.useProfile.mockReturnValue({ data: { restricted: false } });
+
+ const { findByText, getByTestId } = renderWithTheme();
+
+ expect(getByTestId(loadingTestId)).toBeInTheDocument();
+
+ await waitForElementToBeRemoved(getByTestId(loadingTestId));
+ const createClusterButtonSpan = await findByText('Create Database Cluster');
+ const createClusterButton = createClusterButtonSpan.closest('button');
+
+ expect(createClusterButton).toBeInTheDocument();
+ expect(createClusterButton).toBeEnabled();
+ });
+
+ it('should enable form inputs for users with full access', async () => {
+ queryMocks.useProfile.mockReturnValue({ data: { restricted: false } });
+
+ const {
+ findAllByRole,
+ findAllByTestId,
+ findByPlaceholderText,
+ getByTestId,
+ } = renderWithTheme();
+
+ expect(getByTestId(loadingTestId)).toBeInTheDocument();
+
+ await waitForElementToBeRemoved(getByTestId(loadingTestId));
+ const textInputs = await findAllByTestId('textfield-input');
+ textInputs.forEach((input: HTMLInputElement) => {
+ expect(input).toBeEnabled();
+ });
+
+ const dbEngineSelect = await findByPlaceholderText(
+ 'Select a Database Engine'
+ );
+ expect(dbEngineSelect).toBeEnabled();
+ const regionSelect = await findByPlaceholderText('Select a Region');
+ expect(regionSelect).toBeEnabled();
+
+ const radioButtons = await findAllByRole('radio');
+ radioButtons.forEach((radioButton: HTMLElement) => {
+ expect(radioButton).toBeEnabled();
+ });
+ });
});
diff --git a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx
index cb092f26b0e..5ec755d8d25 100644
--- a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx
+++ b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx
@@ -29,6 +29,7 @@ import { RegionSelect } from 'src/components/RegionSelect/RegionSelect';
import { RegionHelperText } from 'src/components/SelectRegionPanel/RegionHelperText';
import { TextField } from 'src/components/TextField';
import { Typography } from 'src/components/Typography';
+import { getRestrictedResourceText } from 'src/features/Account/utils';
import { PlansPanel } from 'src/features/components/PlansPanel/PlansPanel';
import { EngineOption } from 'src/features/Databases/DatabaseCreate/EngineOption';
import { DatabaseLogo } from 'src/features/Databases/DatabaseLanding/DatabaseLogo';
@@ -36,6 +37,7 @@ import { databaseEngineMap } from 'src/features/Databases/DatabaseLanding/Databa
import { useIsDatabasesEnabled } from 'src/features/Databases/utilities';
import { enforceIPMasks } from 'src/features/Firewalls/FirewallDetail/Rules/FirewallRuleDrawer.utils';
import { typeLabelDetails } from 'src/features/Linodes/presentation';
+import { useRestrictedGlobalGrantCheck } from 'src/hooks/useRestrictedGlobalGrantCheck';
import {
useCreateDatabaseMutation,
useDatabaseEnginesQuery,
@@ -48,6 +50,8 @@ import { getSelectedOptionFromGroupedOptions } from 'src/utilities/getSelectedOp
import { validateIPs } from 'src/utilities/ipUtils';
import { scrollErrorIntoViewV2 } from 'src/utilities/scrollErrorIntoViewV2';
+import { DatabaseCreateAccessControls } from './DatabaseCreateAccessControls';
+
import type {
ClusterSize,
ComprehensiveReplicationType,
@@ -62,7 +66,6 @@ import type { Theme } from '@mui/material/styles';
import type { Item } from 'src/components/EnhancedSelect/Select';
import type { PlanSelectionType } from 'src/features/components/PlansPanel/types';
import type { ExtendedIP } from 'src/utilities/ipUtils';
-import { DatabaseCreateAccessControls } from './DatabaseCreateAccessControls';
const useStyles = makeStyles()((theme: Theme) => ({
btnCtn: {
@@ -197,6 +200,9 @@ const DatabaseCreate = () => {
const { classes } = useStyles();
const history = useHistory();
const { isDatabasesV2Beta, isDatabasesV2Enabled } = useIsDatabasesEnabled();
+ const isRestricted = useRestrictedGlobalGrantCheck({
+ globalGrantType: 'add_databases',
+ });
const {
data: regionsData,
@@ -510,6 +516,17 @@ const DatabaseCreate = () => {
}}
title="Create"
/>
+ {isRestricted && (
+
+ )}
{createError && (
@@ -523,6 +540,7 @@ const DatabaseCreate = () => {
Name Your Cluster
setFieldValue('label', e.target.value)}
@@ -544,6 +562,7 @@ const DatabaseCreate = () => {
)}
className={classes.engineSelect}
components={{ Option: EngineOption, SingleValue: _SingleValue }}
+ disabled={isRestricted}
errorText={errors.engine}
isClearable={false}
label="Database Engine"
@@ -555,6 +574,7 @@ const DatabaseCreate = () => {
setFieldValue('region', region.id)}
regions={regionsData}
@@ -570,6 +590,7 @@ const DatabaseCreate = () => {
}}
className={classes.selectPlanPanel}
data-qa-select-plan
+ disabled={isRestricted}
error={errors.type}
handleTabChange={handleTabChange}
header="Choose a Plan"
@@ -599,11 +620,13 @@ const DatabaseCreate = () => {
);
}}
data-testid="database-nodes"
+ disabled={isRestricted}
>
{errors.cluster_size ? (
) : null}
@@ -622,6 +645,7 @@ const DatabaseCreate = () => {
{
) : (