Skip to content

Commit 3de595b

Browse files
committed
Add Changes for UI side and disable endpoints
1 parent 5f10400 commit 3de595b

File tree

8 files changed

+153
-16
lines changed

8 files changed

+153
-16
lines changed

openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/SystemRepository.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,61 @@ public SystemRepository() {
127127
migrationValidationClient = MigrationValidationClient.getInstance();
128128
}
129129

130-
public boolean isUpdateAllowed(Settings setting) {
131-
Object configValue = setting.getConfigValue();
130+
public boolean isUpdateAllowed(SettingsType configType) {
131+
// Fetch the existing setting from DB to check its configSource
132+
// We check the DB value, not the incoming request, to prevent bypass
133+
Settings existingSetting = getConfigWithKey(configType.value());
134+
if (existingSetting == null) {
135+
return true;
136+
}
137+
138+
Object configValue = existingSetting.getConfigValue();
139+
if (configValue == null) {
140+
return true;
141+
}
142+
143+
// If already the correct type, use it directly
132144
if (configValue instanceof OpenMetadataConfig openMetadataConfig) {
133145
ConfigSource source = openMetadataConfig.getConfigSource();
134146
return source != ConfigSource.ENV;
135147
}
148+
149+
// Convert LinkedHashMap to proper class based on configType
150+
OpenMetadataConfig config = convertToOpenMetadataConfig(configType, configValue);
151+
if (config != null) {
152+
ConfigSource source = config.getConfigSource();
153+
return source != ConfigSource.ENV;
154+
}
155+
136156
return true;
137157
}
138158

159+
private OpenMetadataConfig convertToOpenMetadataConfig(
160+
SettingsType configType, Object configValue) {
161+
if (configType == null || configValue == null) {
162+
return null;
163+
}
164+
try {
165+
return switch (configType) {
166+
case EMAIL_CONFIGURATION -> JsonUtils.convertValue(configValue, SmtpSettings.class);
167+
case AUTHENTICATION_CONFIGURATION -> JsonUtils.convertValue(
168+
configValue, AuthenticationConfiguration.class);
169+
case AUTHORIZER_CONFIGURATION -> JsonUtils.convertValue(
170+
configValue, AuthorizerConfiguration.class);
171+
case SEARCH_SETTINGS -> JsonUtils.convertValue(configValue, SearchSettings.class);
172+
case CUSTOM_UI_THEME_PREFERENCE -> JsonUtils.convertValue(
173+
configValue, UiThemePreference.class);
174+
case SCIM_CONFIGURATION -> JsonUtils.convertValue(configValue, ScimConfiguration.class);
175+
case ASSET_CERTIFICATION_SETTINGS -> JsonUtils.convertValue(
176+
configValue, AssetCertificationSettings.class);
177+
case WORKFLOW_SETTINGS -> JsonUtils.convertValue(configValue, WorkflowSettings.class);
178+
default -> null;
179+
};
180+
} catch (Exception e) {
181+
return null;
182+
}
183+
}
184+
139185
public String getEnvHash(String configType) {
140186
return dao.getEnvHash(configType);
141187
}

openmetadata-service/src/main/java/org/openmetadata/service/resources/system/SystemResource.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ public Response createOrUpdateSetting(
360360
}
361361

362362
authorizer.authorizeAdmin(securityContext);
363-
if (!systemRepository.isUpdateAllowed(settingName)) {
363+
if (!systemRepository.isUpdateAllowed(settingName.getConfigType())) {
364364
throw new IllegalArgumentException(
365365
"This setting is managed by ENV configuration and cannot be updated via API. "
366366
+ "Change configSource to DB or AUTO to enable API updates.");
@@ -489,6 +489,15 @@ public Response patch(
489489
}
490490

491491
authorizer.authorizeAdmin(securityContext);
492+
493+
// Check if update is allowed based on configSource
494+
SettingsType settingsType = SettingsType.fromValue(settingName);
495+
if (!systemRepository.isUpdateAllowed(settingsType)) {
496+
throw new IllegalArgumentException(
497+
"This setting is managed by ENV configuration and cannot be updated via API. "
498+
+ "Change configSource to DB or AUTO to enable API updates.");
499+
}
500+
492501
return systemRepository.patchSetting(settingName, patch);
493502
}
494503

@@ -645,6 +654,19 @@ public Response updateSecurityConfig(
645654
@Valid SecurityConfiguration securityConfig) {
646655
authorizer.authorizeAdmin(securityContext);
647656

657+
// Check if update is allowed based on configSource for both configs
658+
if (!systemRepository.isUpdateAllowed(AUTHENTICATION_CONFIGURATION)) {
659+
throw new IllegalArgumentException(
660+
"Authentication configuration is managed by ENV and cannot be updated via API. "
661+
+ "Change configSource to DB or AUTO to enable API updates.");
662+
}
663+
664+
if (!systemRepository.isUpdateAllowed(AUTHORIZER_CONFIGURATION)) {
665+
throw new IllegalArgumentException(
666+
"Authorizer configuration is managed by ENV and cannot be updated via API. "
667+
+ "Change configSource to DB or AUTO to enable API updates.");
668+
}
669+
648670
try {
649671
// Update both configurations in a transaction
650672
Settings authSettings =
@@ -700,6 +722,19 @@ public Response patchSecurityConfig(
700722
JsonPatch patch) {
701723
authorizer.authorizeAdmin(securityContext);
702724

725+
// Check if update is allowed based on configSource for both configs
726+
if (!systemRepository.isUpdateAllowed(AUTHENTICATION_CONFIGURATION)) {
727+
throw new IllegalArgumentException(
728+
"Authentication configuration is managed by ENV and cannot be updated via API. "
729+
+ "Change configSource to DB or AUTO to enable API updates.");
730+
}
731+
732+
if (!systemRepository.isUpdateAllowed(AUTHORIZER_CONFIGURATION)) {
733+
throw new IllegalArgumentException(
734+
"Authorizer configuration is managed by ENV and cannot be updated via API. "
735+
+ "Change configSource to DB or AUTO to enable API updates.");
736+
}
737+
703738
try {
704739
SecurityConfiguration originalConfig =
705740
SecurityConfigurationManager.getInstance().getCurrentSecurityConfig();

openmetadata-ui/src/main/resources/ui/src/components/SettingsSso/SettingsSso.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { useTranslation } from 'react-i18next';
1616
import { useSearchParams } from 'react-router-dom';
1717
import { GlobalSettingsMenuCategory } from '../../constants/GlobalSettings.constants';
1818
import { AuthProvider } from '../../generated/settings/settings';
19+
import { ConfigSource } from '../../generated/type/configSource';
1920
import {
2021
getSecurityConfiguration,
2122
patchSecurityConfiguration,
@@ -29,6 +30,7 @@ import { getProviderDisplayName, getProviderIcon } from '../../utils/SSOUtils';
2930
import Loader from '../common/Loader/Loader';
3031
import TitleBreadcrumb from '../common/TitleBreadcrumb/TitleBreadcrumb.component';
3132
import PageLayoutV1 from '../PageLayoutV1/PageLayoutV1';
33+
import ConfigSourceIndicator from '../Settings/ConfigSourceIndicator';
3234
import ProviderSelector from './ProviderSelector/ProviderSelector';
3335
import './settings-sso.less';
3436
import SSOConfigurationForm from './SSOConfigurationForm/SSOConfigurationForm';
@@ -327,6 +329,14 @@ const SettingsSso = () => {
327329
setActiveTab(key);
328330
}, []);
329331

332+
const isEnvManaged = useMemo(() => {
333+
return (
334+
securityConfig?.authenticationConfiguration?.configSource ===
335+
ConfigSource.ENV ||
336+
securityConfig?.authorizerConfiguration?.configSource === ConfigSource.ENV
337+
);
338+
}, [securityConfig]);
339+
330340
const handleProviderSelect = useCallback(
331341
(provider: AuthProvider) => {
332342
setCurrentProvider(provider);
@@ -424,6 +434,12 @@ const SettingsSso = () => {
424434
</div>
425435
)}
426436

437+
{isEnvManaged && (
438+
<div className="m-b-md">
439+
<ConfigSourceIndicator configSource={ConfigSource.ENV} />
440+
</div>
441+
)}
442+
427443
<Tabs
428444
activeKey={activeTab}
429445
items={tabItems}

openmetadata-ui/src/main/resources/ui/src/constants/EmailConfig.constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ export const TRANSPORTATION_STRATEGY_OPTIONS = Object.values(
2020
value: strategy,
2121
}));
2222

23-
export const NOT_INCLUDE_EMAIL_CONFIG_VALUE = ['templates'];
23+
export const NOT_INCLUDE_EMAIL_CONFIG_VALUE = ['templates', 'configSource'];

openmetadata-ui/src/main/resources/ui/src/constants/SSO.constant.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313

1414
import { ClientType } from '../generated/configuration/securityConfiguration';
15+
import { ConfigSource } from '../generated/type/configSource';
1516
import {
1617
getAuthorityUrl,
1718
getCallbackUrl,
@@ -683,6 +684,7 @@ export const VALIDATION_STATUS = {
683684
} as const;
684685

685686
export interface AuthenticationConfiguration {
687+
configSource?: ConfigSource;
686688
provider: string;
687689
providerName: string;
688690
authority: string;
@@ -702,6 +704,7 @@ export interface AuthenticationConfiguration {
702704
}
703705

704706
export interface AuthorizerConfiguration {
707+
configSource?: ConfigSource;
705708
className: string;
706709
containerRequestFilter: string;
707710
adminPrincipals: string[];

openmetadata-ui/src/main/resources/ui/src/generated/email/smtpSettings.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@
1010
* See the License for the specific language governing permissions and
1111
* limitations under the License.
1212
*/
13+
import { ConfigSource } from '../type/configSource';
14+
1315
/**
1416
* This schema defines the SMTP Settings for sending Email
1517
*/
1618
export interface SMTPSettings {
19+
/**
20+
* Determines where this configuration is read from.
21+
*/
22+
configSource?: ConfigSource;
1723
/**
1824
* Emailing Entity
1925
*/
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2025 Collate.
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
* limitations under the License.
12+
*/
13+
/**
14+
* Determines where configuration is read from.
15+
*/
16+
export enum ConfigSource {
17+
ENV = 'ENV',
18+
DB = 'DB',
19+
AUTO = 'AUTO',
20+
}

openmetadata-ui/src/main/resources/ui/src/pages/EmailConfigSettingsPage/EmailConfigSettingsPage.component.tsx

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ import TitleBreadcrumb from '../../components/common/TitleBreadcrumb/TitleBreadc
2525
import { TitleBreadcrumbProps } from '../../components/common/TitleBreadcrumb/TitleBreadcrumb.interface';
2626
import PageHeader from '../../components/PageHeader/PageHeader.component';
2727
import PageLayoutV1 from '../../components/PageLayoutV1/PageLayoutV1';
28+
import ConfigSourceIndicator from '../../components/Settings/ConfigSourceIndicator';
2829
import TestEmail from '../../components/Settings/Email/TestEmail/TestEmail.component';
2930
import { ROUTES } from '../../constants/constants';
3031
import { NOT_INCLUDE_EMAIL_CONFIG_VALUE } from '../../constants/EmailConfig.constants';
3132
import { GlobalSettingsMenuCategory } from '../../constants/GlobalSettings.constants';
3233
import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum';
3334
import { SMTPSettings } from '../../generated/email/smtpSettings';
3435
import { SettingType } from '../../generated/settings/settings';
36+
import { ConfigSource } from '../../generated/type/configSource';
3537
import { useAuth } from '../../hooks/authHooks';
3638
import { getSettingsConfigFromConfigType } from '../../rest/settingConfigAPI';
3739
import { getEmailConfigFieldLabels } from '../../utils/EmailConfigUtils';
@@ -181,22 +183,31 @@ function EmailConfigSettingsPage() {
181183
{loading ? (
182184
<ButtonSkeleton />
183185
) : (
184-
<Button
185-
className="m-l-md"
186-
icon={
187-
!isUndefined(emailConfigValues) && (
188-
<Icon component={IconEdit} size={12} />
189-
)
190-
}
191-
onClick={handleEditClick}>
192-
{isUndefined(emailConfigValues)
193-
? t('label.add')
194-
: t('label.edit')}
195-
</Button>
186+
emailConfigValues?.configSource !== ConfigSource.ENV && (
187+
<Button
188+
className="m-l-md"
189+
icon={
190+
!isUndefined(emailConfigValues) && (
191+
<Icon component={IconEdit} size={12} />
192+
)
193+
}
194+
onClick={handleEditClick}>
195+
{isUndefined(emailConfigValues)
196+
? t('label.add')
197+
: t('label.edit')}
198+
</Button>
199+
)
196200
)}
197201
</Col>
198202
</Row>
199203
</Col>
204+
{emailConfigValues?.configSource && (
205+
<Col span={24}>
206+
<ConfigSourceIndicator
207+
configSource={emailConfigValues.configSource}
208+
/>
209+
</Col>
210+
)}
200211
<Col span={24}>{configValuesContainer}</Col>
201212
</Row>
202213

0 commit comments

Comments
 (0)