diff --git a/public/app/features/admin/ldap/LdapDrawer.tsx b/public/app/features/admin/ldap/LdapDrawer.tsx
index 42b3abdc660..caa5edefa1f 100644
--- a/public/app/features/admin/ldap/LdapDrawer.tsx
+++ b/public/app/features/admin/ldap/LdapDrawer.tsx
@@ -60,7 +60,7 @@ export const LdapDrawerComponent = ({
useEffect(() => {
const { client_cert, client_key, root_ca_cert } = getValues(serverConfig);
setEncryptionProvider(
- !client_cert.length && !client_key.length && !root_ca_cert?.length
+ !client_cert?.length && !client_key?.length && !root_ca_cert?.length
? EncryptionProvider.Base64
: EncryptionProvider.FilePath
);
@@ -83,19 +83,21 @@ export const LdapDrawerComponent = ({
);
const useTlsDescription = (
-
- For a complete list of supported ciphers and TLS versions, refer to:{' '}
- {
-
- https://go.dev/src/crypto/tls/cipher_suites.go
-
- }
-
+ <>
+
+ For a complete list of supported ciphers and TLS versions, refer to:
+ {' '}
+ {/* eslint-disable-next-line @grafana/no-untranslated-strings */}
+
+ https://go.dev/src/crypto/tls/cipher_suites.go
+
+ >
);
const onAddGroupMapping = () => {
+ const groupMappings = getValues(`${serverConfig}.group_mappings`) || [];
setValue(`${serverConfig}.group_mappings`, [
- ...getValues(`${serverConfig}.group_mappings`),
+ ...groupMappings,
{
group_dn: '',
org_id: 1,
@@ -338,10 +340,12 @@ export const LdapDrawerComponent = ({
(
+ render={({ field: { onChange, ref, value, ...field } }) => (
onChange(v.map(({ value }) => String(value)))}
value={value?.map((v) => ({ label: renderMultiSelectLabel(v), value: v }))}
/>
@@ -447,5 +451,10 @@ function getStyles(theme: GrafanaTheme2) {
button: css({
marginBottom: theme.spacing(4),
}),
+ multiSelect: css({
+ svg: {
+ display: 'none',
+ },
+ }),
};
}
diff --git a/public/app/features/admin/ldap/LdapSettingsPage.tsx b/public/app/features/admin/ldap/LdapSettingsPage.tsx
index 7b7335cc649..736a40a76c5 100644
--- a/public/app/features/admin/ldap/LdapSettingsPage.tsx
+++ b/public/app/features/admin/ldap/LdapSettingsPage.tsx
@@ -4,7 +4,7 @@ import { Controller, FormProvider, useForm } from 'react-hook-form';
import { connect } from 'react-redux';
import { AppEvents, GrafanaTheme2, NavModelItem } from '@grafana/data';
-import { getBackendSrv, getAppEvents } from '@grafana/runtime';
+import { getBackendSrv, getAppEvents, reportInteraction } from '@grafana/runtime';
import {
useStyles2,
Alert,
@@ -15,12 +15,14 @@ import {
Input,
LinkButton,
Menu,
+ Modal,
Stack,
Text,
TextLink,
Dropdown,
MultiSelect,
} from '@grafana/ui';
+import { FormPrompt } from 'app/core/components/FormPrompt/FormPrompt';
import { Page } from 'app/core/components/Page/Page';
import config from 'app/core/config';
import { t, Trans } from 'app/core/internationalization';
@@ -94,6 +96,7 @@ const emptySettings: LdapPayload = {
export const LdapSettingsPage = () => {
const [isLoading, setIsLoading] = useState(true);
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
+ const [isModalOpen, setIsModalOpen] = useState(false);
const [mapKeyCertConfigured, setMapKeyCertConfigured] = useState({
// values
@@ -107,14 +110,25 @@ export const LdapSettingsPage = () => {
});
const methods = useForm({ defaultValues: emptySettings });
- const { control, getValues, handleSubmit, register, reset, watch } = methods;
+ const {
+ control,
+ formState: { isDirty },
+ getValues,
+ handleSubmit,
+ register,
+ reset,
+ watch,
+ } = methods;
const styles = useStyles2(getStyles);
useEffect(() => {
async function init() {
const payload = await getSettings();
- const serverConfig = payload.settings.config.servers[0];
+ let serverConfig = emptySettings.settings.config.servers[0];
+ if (payload.settings.config.servers?.length > 0) {
+ serverConfig = payload.settings.config.servers[0];
+ }
setMapKeyCertConfigured({
rootCaCertValue: serverConfig.root_ca_cert_value?.length > 0,
clientCertValue: serverConfig.client_cert_value !== '',
@@ -203,12 +217,14 @@ export const LdapSettingsPage = () => {
/**
* Button's Actions
*/
- const submitAndEnableLdapSettings = (payload: LdapPayload) => {
+ const submitAndEnableLdapSettings = async (payload: LdapPayload) => {
payload.settings.enabled = true;
- putPayload(payload);
+ await putPayload(payload);
+ reportInteraction('authentication_ldap_enabled');
};
- const saveForm = () => {
- putPayload(getValues());
+ const saveForm = async () => {
+ await putPayload(getValues());
+ reportInteraction('authentication_ldap_saved');
};
const deleteLDAPConfig = async () => {
try {
@@ -220,6 +236,7 @@ export const LdapSettingsPage = () => {
payload: [t('ldap-settings-page.alert.discard-success', 'LDAP settings discarded')],
});
reset(payload);
+ reportInteraction('authentication_ldap_deleted');
} catch (error) {
appEvents.publish({
type: AppEvents.alertError.name,
@@ -230,6 +247,10 @@ export const LdapSettingsPage = () => {
}
};
+ const onDiscard = () => {
+ reportInteraction('authentication_ldap_abandoned');
+ };
+
const subTitle = (
The LDAP integration in Grafana allows your Grafana users to log in with their LDAP credentials. Find out more in
@@ -259,6 +280,7 @@ export const LdapSettingsPage = () => {
{config.disableLoginForm && disabledFormAlert}
+ setIsModalOpen(false)}
+ >
+
+
+ Are you sure you want to abandon the changes you‘ve made to the LDAP configuration? All changes will
+ be lost.
+
+
+
+
+
+
+
);
};
@@ -401,6 +445,11 @@ function getStyles(theme: GrafanaTheme2) {
form: css({
width: theme.spacing(68),
}),
+ multiSelect: css({
+ svg: {
+ display: 'none',
+ },
+ }),
};
}
diff --git a/public/app/features/auth-config/AuthProvidersListPage.tsx b/public/app/features/auth-config/AuthProvidersListPage.tsx
index 560c1a3a79a..717906f0f3a 100644
--- a/public/app/features/auth-config/AuthProvidersListPage.tsx
+++ b/public/app/features/auth-config/AuthProvidersListPage.tsx
@@ -57,7 +57,13 @@ export const AuthConfigPageUnconnected = ({
providers = providers.map((p) => {
if (p.provider === 'ldap') {
- p.settings.type = p.provider;
+ return {
+ ...p,
+ settings: {
+ ...p.settings,
+ type: 'LDAP',
+ },
+ };
}
return p;
});
diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json
index b20956af416..66dd73190d3 100644
--- a/public/locales/en-US/grafana.json
+++ b/public/locales/en-US/grafana.json
@@ -1091,7 +1091,7 @@
"tls-ciphers-placeholder": "e.g. [\"TLS_AES_256_GCM_SHA384\"]",
"use-ssl-description": "Set to true if LDAP server should use TLS connection (either with STARTTLS or LDAPS)",
"use-ssl-label": "Use SSL",
- "use-ssl-tooltip": "For a complete list of supported ciphers and TLS versions, refer to: {\n \n https://go.dev/src/crypto/tls/cipher_suites.go\n }"
+ "use-ssl-tooltip": "For a complete list of supported ciphers and TLS versions, refer to:"
},
"group-mapping": {
"grafana-admin": {
@@ -1141,9 +1141,7 @@
},
"ldap-settings-page": {
"advanced-settings-section": {
- "edit": {
- "button": "Edit"
- },
+ "edit-button": "Edit",
"subtitle": "Mappings, extra security measures, and more.",
"title": "Advanced Settings"
},
@@ -1164,20 +1162,20 @@
"label": "Bind password"
},
"buttons-section": {
- "discard": {
- "button": "Discard"
- },
- "save": {
- "button": "Save"
- },
- "save-and-enable": {
- "button": "Save and enable"
- }
+ "discard-button": "Discard",
+ "save-and-enable-button": "Save and enable",
+ "save-button": "Save"
+ },
+ "discard-modal": {
+ "cancel-button": "Back to editing",
+ "description": "Are you sure you want to abandon the changes you‘ve made to the LDAP configuration? All changes will be lost.",
+ "discard-button": "Abandon LDAP",
+ "title": "Leave LDAP configuration?"
},
"documentation": "documentation",
"host": {
"description": "Hostname or IP address of the LDAP server you wish to connect to.",
- "label": "Server host",
+ "label": "Server host *",
"placeholder": "example: 127.0.0.1"
},
"login-form-alert": {
@@ -1186,7 +1184,7 @@
},
"search_filter": {
"description": "LDAP search filter used to locate specific entries within the directory.",
- "label": "Search filter*",
+ "label": "Search filter *",
"placeholder": "example: cn=%s"
},
"search-base-dns": {
diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json
index 8ac07e0c62d..9cb08bd3fc4 100644
--- a/public/locales/pseudo-LOCALE/grafana.json
+++ b/public/locales/pseudo-LOCALE/grafana.json
@@ -1091,7 +1091,7 @@
"tls-ciphers-placeholder": "ę.ģ. [\"ŦĿŜ_ÅĒŜ_256_ĞCM_ŜĦÅ384\"]",
"use-ssl-description": "Ŝęŧ ŧő ŧřūę įƒ ĿĐÅP şęřvęř şĥőūľđ ūşę ŦĿŜ čőʼnʼnęčŧįőʼn (ęįŧĥęř ŵįŧĥ ŜŦÅŖŦŦĿŜ őř ĿĐÅPŜ)",
"use-ssl-label": "Ůşę ŜŜĿ",
- "use-ssl-tooltip": "Főř ä čőmpľęŧę ľįşŧ őƒ şūppőřŧęđ čįpĥęřş äʼnđ ŦĿŜ vęřşįőʼnş, řęƒęř ŧő: {\n <ŦęχŧĿįʼnĸ şŧyľę={{ fontSize: 'inherit' }} ĥřęƒ=\"ĥŧŧpş://ģő.đęv/şřč/čřypŧő/ŧľş/čįpĥęř_şūįŧęş.ģő\" ęχŧęřʼnäľ>\n ĥŧŧpş://ģő.đęv/şřč/čřypŧő/ŧľş/čįpĥęř_şūįŧęş.ģő\n ŦęχŧĿįʼnĸ>}"
+ "use-ssl-tooltip": "Főř ä čőmpľęŧę ľįşŧ őƒ şūppőřŧęđ čįpĥęřş äʼnđ ŦĿŜ vęřşįőʼnş, řęƒęř ŧő:"
},
"group-mapping": {
"grafana-admin": {
@@ -1141,9 +1141,7 @@
},
"ldap-settings-page": {
"advanced-settings-section": {
- "edit": {
- "button": "Ēđįŧ"
- },
+ "edit-button": "Ēđįŧ",
"subtitle": "Mäppįʼnģş, ęχŧřä şęčūřįŧy męäşūřęş, äʼnđ mőřę.",
"title": "Åđväʼnčęđ Ŝęŧŧįʼnģş"
},
@@ -1164,20 +1162,20 @@
"label": "ßįʼnđ päşşŵőřđ"
},
"buttons-section": {
- "discard": {
- "button": "Đįşčäřđ"
- },
- "save": {
- "button": "Ŝävę"
- },
- "save-and-enable": {
- "button": "Ŝävę äʼnđ ęʼnäþľę"
- }
+ "discard-button": "Đįşčäřđ",
+ "save-and-enable-button": "Ŝävę äʼnđ ęʼnäþľę",
+ "save-button": "Ŝävę"
+ },
+ "discard-modal": {
+ "cancel-button": "ßäčĸ ŧő ęđįŧįʼnģ",
+ "description": "Åřę yőū şūřę yőū ŵäʼnŧ ŧő äþäʼnđőʼn ŧĥę čĥäʼnģęş yőū&ľşqūő;vę mäđę ŧő ŧĥę ĿĐÅP čőʼnƒįģūřäŧįőʼn? Åľľ čĥäʼnģęş ŵįľľ þę ľőşŧ.",
+ "discard-button": "Åþäʼnđőʼn ĿĐÅP",
+ "title": "Ŀęävę ĿĐÅP čőʼnƒįģūřäŧįőʼn?"
},
"documentation": "đőčūmęʼnŧäŧįőʼn",
"host": {
"description": "Ħőşŧʼnämę őř ĨP äđđřęşş őƒ ŧĥę ĿĐÅP şęřvęř yőū ŵįşĥ ŧő čőʼnʼnęčŧ ŧő.",
- "label": "Ŝęřvęř ĥőşŧ",
+ "label": "Ŝęřvęř ĥőşŧ *",
"placeholder": "ęχämpľę: 127.0.0.1"
},
"login-form-alert": {
@@ -1186,7 +1184,7 @@
},
"search_filter": {
"description": "ĿĐÅP şęäřčĥ ƒįľŧęř ūşęđ ŧő ľőčäŧę şpęčįƒįč ęʼnŧřįęş ŵįŧĥįʼn ŧĥę đįřęčŧőřy.",
- "label": "Ŝęäřčĥ ƒįľŧęř*",
+ "label": "Ŝęäřčĥ ƒįľŧęř *",
"placeholder": "ęχämpľę: čʼn=%ş"
},
"search-base-dns": {