mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
SSO LDAP: Add LDAP settings drawer (#92199)
* Add LdapDrawer component * Add success message for discarding LDAP settings * Add Use SSL tooltip * Add min tls version field * Change alert error to alert success * Add tls ciphers field * Update i18n * rename ssl for tls * rename ldap to LDAP
This commit is contained in:
parent
922babb157
commit
9fbfaf08a6
251
public/app/features/admin/ldap/LdapDrawer.tsx
Normal file
251
public/app/features/admin/ldap/LdapDrawer.tsx
Normal file
@ -0,0 +1,251 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
|
||||
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
|
||||
import {
|
||||
useStyles2,
|
||||
CollapsableSection,
|
||||
Divider,
|
||||
Drawer,
|
||||
Field,
|
||||
Icon,
|
||||
Input,
|
||||
Label,
|
||||
Select,
|
||||
Stack,
|
||||
Switch,
|
||||
Text,
|
||||
TextLink,
|
||||
Tooltip,
|
||||
} from '@grafana/ui';
|
||||
import { t, Trans } from 'app/core/internationalization';
|
||||
import { LdapPayload } from 'app/types';
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const tlsOptions: Array<SelectableValue<string>> = ['TLS1.2', 'TLS1.3'].map((v) => ({ label: v, value: v }));
|
||||
|
||||
export const LdapDrawerComponent = ({ onClose }: Props) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
const { register, setValue, watch } = useFormContext<LdapPayload>();
|
||||
|
||||
const groupMappingsLabel = (
|
||||
<Label
|
||||
className={styles.sectionLabel}
|
||||
description={t('ldap-drawer.group-mapping-section.description', 'Map LDAP groups to Grafana org roles')}
|
||||
>
|
||||
<Trans i18nKey="ldap-drawer.group-mapping-section.label">Group mapping</Trans>
|
||||
</Label>
|
||||
);
|
||||
|
||||
const useTlsDescription = (
|
||||
<Trans i18nKey="ldap-drawer.extra-security-section.use-ssl.tooltip">
|
||||
For a complete list of supported ciphers and TLS versions, refer to:{' '}
|
||||
{
|
||||
<TextLink style={{ fontSize: 'inherit' }} href="https://go.dev/src/crypto/tls/cipher_suites.go" external>
|
||||
https://go.dev/src/crypto/tls/cipher_suites.go
|
||||
</TextLink>
|
||||
}
|
||||
</Trans>
|
||||
);
|
||||
|
||||
return (
|
||||
<Drawer title={t('ldap-drawer.title', 'Advanced Settings')} onClose={onClose}>
|
||||
<CollapsableSection label={t('ldap-drawer.misc-section.label', 'Misc')} isOpen={true}>
|
||||
<Field
|
||||
label={t('ldap-drawer.misc-section.allow-sign-up.label', 'Allow sign up')}
|
||||
description={t(
|
||||
'ldap-drawer.misc-section.allow-sign-up.descrition',
|
||||
'If not enabled, only existing Grafana users can log in using LDAP'
|
||||
)}
|
||||
>
|
||||
<Switch id="allow-sign-up" {...register('settings.allowSignUp')} />
|
||||
</Field>
|
||||
<Field
|
||||
label={t('ldap-drawer.misc-section.port.label', 'Port')}
|
||||
description={t(
|
||||
'ldap-drawer.misc-section.port.description',
|
||||
'Default port is 389 without SSL or 636 with SSL'
|
||||
)}
|
||||
>
|
||||
<Input
|
||||
id="port"
|
||||
placeholder={t('ldap-drawer.misc-section.port.placeholder', '389')}
|
||||
type="number"
|
||||
{...register('settings.config.servers.0.port', { valueAsNumber: true })}
|
||||
/>
|
||||
</Field>
|
||||
<Field
|
||||
label={t('ldap-drawer.misc-section.timeout.label', 'Timeout')}
|
||||
description={t(
|
||||
'ldap-drawer.misc-section.timeout.description',
|
||||
'Timeout in seconds for the connection to the LDAP server'
|
||||
)}
|
||||
>
|
||||
<Input
|
||||
id="timeout"
|
||||
placeholder={t('ldap-drawer.misc-section.timeout.placeholder', '389')}
|
||||
type="number"
|
||||
{...register('settings.config.servers.0.timeout', { valueAsNumber: true })}
|
||||
/>
|
||||
</Field>
|
||||
</CollapsableSection>
|
||||
<CollapsableSection label={t('ldap-drawer.attributes-section.label', 'Attributes')} isOpen={true}>
|
||||
<Text color="secondary">
|
||||
<Trans i18nKey="ldap-drawer.attributes-section.description">
|
||||
Specify the LDAP attributes that map to the user‘s given name, surname, and email address, ensuring
|
||||
the application correctly retrieves and displays user information.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Field htmlFor="name" label={t('ldap-drawer.attributes-section.name.label', 'Name')}>
|
||||
<Input id="name" {...register('settings.config.servers.0.attributes.name')} />
|
||||
</Field>
|
||||
<Field htmlFor="surname" label={t('ldap-drawer.attributes-section.surname.label', 'Surname')}>
|
||||
<Input id="surname" {...register('settings.config.servers.0.attributes.surname')} />
|
||||
</Field>
|
||||
<Field htmlFor="username" label={t('ldap-drawer.attributes-section.username.label', 'Username')}>
|
||||
<Input id="username" {...register('settings.config.servers.0.attributes.username')} />
|
||||
</Field>
|
||||
<Field htmlFor="member-of" label={t('ldap-drawer.attributes-section.member-of.label', 'Member Of')}>
|
||||
<Input id="member-of" {...register('settings.config.servers.0.attributes.member_of')} />
|
||||
</Field>
|
||||
<Field htmlFor="email" label={t('ldap-drawer.attributes-section.email.label', 'Email')}>
|
||||
<Input id="email" {...register('settings.config.servers.0.attributes.email')} />
|
||||
</Field>
|
||||
</CollapsableSection>
|
||||
<CollapsableSection label={groupMappingsLabel} isOpen={true}>
|
||||
<Field
|
||||
htmlFor="skip-org-role-sync"
|
||||
label={t('ldap-drawer.group-mapping-section.skip-org-role-sync.label', 'Skip organization role sync')}
|
||||
description={t(
|
||||
'ldap-drawer.group-mapping-section.skip-org-role-sync.description',
|
||||
'Prevent synchronizing users’ organization roles from your IdP'
|
||||
)}
|
||||
>
|
||||
<Switch id="skip-org-role-sync" {...register('settings.config.servers.0.skip_org_role_sync')} />
|
||||
</Field>
|
||||
<Field
|
||||
htmlFor="group-search-filter"
|
||||
label={t('ldap-drawer.group-mapping-section.group-search-filter.label', 'Group search filter')}
|
||||
description={t(
|
||||
'ldap-drawer.group-mapping-section.group-search-filter.description',
|
||||
'Used to filter and identify group entries within the directory'
|
||||
)}
|
||||
>
|
||||
<Input id="group-search-filter" {...register('settings.config.servers.0.group_search_filter')} />
|
||||
</Field>
|
||||
<Field
|
||||
htmlFor="group-search-base-dns"
|
||||
label={t('ldap-drawer.group-mapping-section.group-search-base-dns.label', 'Group search base DNS')}
|
||||
description={t(
|
||||
'ldap-drawer.group-mapping-section.group-search-base-dns.description',
|
||||
'Separate by commas or spaces'
|
||||
)}
|
||||
>
|
||||
<Input
|
||||
id="group-search-base-dns"
|
||||
onChange={({ currentTarget: { value } }) =>
|
||||
setValue('settings.config.servers.0.group_search_base_dns', [value])
|
||||
}
|
||||
/>
|
||||
</Field>
|
||||
<Field
|
||||
htmlFor="group-search-filter-user-attribute"
|
||||
label={t(
|
||||
'ldap-drawer.group-mapping-section.group-search-filter-user-attribute.label',
|
||||
'Group name attribute'
|
||||
)}
|
||||
description={t(
|
||||
'ldap-drawer.group-mapping-section.group-search-filter-user-attribute.description',
|
||||
'Identifies users within group entries for filtering purposes'
|
||||
)}
|
||||
>
|
||||
<Input
|
||||
id="group-search-filter-user-attribute"
|
||||
{...register('settings.config.servers.0.group_search_filter_user_attribute')}
|
||||
/>
|
||||
</Field>
|
||||
<Divider />
|
||||
</CollapsableSection>
|
||||
<CollapsableSection
|
||||
label={t('ldap-drawer.extra-security-section.label', 'Extra security measures')}
|
||||
isOpen={true}
|
||||
>
|
||||
<Field
|
||||
label={t('ldap-drawer.extra-security-section.use-ssl.label', 'Use SSL')}
|
||||
description={t(
|
||||
'ldap-drawer.extra-security-section.use-ssl.description',
|
||||
'Set to true if LDAP server should use TLS connection (either with STARTTLS or LDAPS)'
|
||||
)}
|
||||
>
|
||||
<Stack>
|
||||
<Switch id="use-ssl" {...register('settings.config.servers.0.use_ssl')} />
|
||||
<Tooltip content={useTlsDescription} interactive>
|
||||
<Icon name="info-circle" />
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
</Field>
|
||||
{watch('settings.config.servers.0.use_ssl') && (
|
||||
<>
|
||||
<Field
|
||||
label={t('ldap-drawer.extra-security-section.start-tls.label', 'Start TLS')}
|
||||
description={t(
|
||||
'ldap-drawer.extra-security-section.start-tls.description',
|
||||
'If set to true, use LDAP with STARTTLS instead of LDAPS'
|
||||
)}
|
||||
>
|
||||
<Switch id="start-tls" {...register('settings.config.servers.0.start_tls')} />
|
||||
</Field>
|
||||
<Field
|
||||
htmlFor="min-tls-version"
|
||||
label={t('ldap-drawer.extra-security-section.min-tls-version.label', 'Min TLS version')}
|
||||
description={t(
|
||||
'ldap-drawer.extra-security-section.min-tls-version.description',
|
||||
'This is the minimum TLS version allowed. Accepted values are: TLS1.2, TLS1.3.'
|
||||
)}
|
||||
>
|
||||
<Select
|
||||
id="min-tls-version"
|
||||
options={tlsOptions}
|
||||
value={watch('settings.config.servers.0.min_tls_version')}
|
||||
onChange={({ value }) => setValue('settings.config.servers.0.min_tls_version', value)}
|
||||
/>
|
||||
</Field>
|
||||
<Field
|
||||
label={t('ldap-drawer.extra-security-section.tls-ciphers.label', 'TLS ciphers')}
|
||||
description={t(
|
||||
'ldap-drawer.extra-security-section.tls-ciphers.description',
|
||||
'List of comma- or space-separated ciphers'
|
||||
)}
|
||||
>
|
||||
<Input
|
||||
id="tls-ciphers"
|
||||
placeholder={t(
|
||||
'ldap-drawer.extra-security-section.tls-ciphers.placeholder',
|
||||
'e.g. ["TLS_AES_256_GCM_SHA384"]'
|
||||
)}
|
||||
value={watch('settings.config.servers.0.tls_ciphers')}
|
||||
onChange={({ currentTarget: { value } }) =>
|
||||
setValue(
|
||||
'settings.config.servers.0.tls_ciphers',
|
||||
value?.split(/,|\s/).map((v: string) => v.trim())
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Field>
|
||||
</>
|
||||
)}
|
||||
</CollapsableSection>
|
||||
</Drawer>
|
||||
);
|
||||
};
|
||||
|
||||
function getStyles(theme: GrafanaTheme2) {
|
||||
return {
|
||||
sectionLabel: css({
|
||||
fontSize: theme.typography.size.lg,
|
||||
}),
|
||||
};
|
||||
}
|
@ -5,13 +5,15 @@ import { connect } from 'react-redux';
|
||||
|
||||
import { AppEvents, GrafanaTheme2, NavModelItem } from '@grafana/data';
|
||||
import { getBackendSrv, getAppEvents } from '@grafana/runtime';
|
||||
import { useStyles2, Alert, Box, Button, Field, Input, Stack, TextLink } from '@grafana/ui';
|
||||
import { useStyles2, Alert, Box, Button, Field, Input, Stack, Text, TextLink } from '@grafana/ui';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
import config from 'app/core/config';
|
||||
import { t, Trans } from 'app/core/internationalization';
|
||||
import { Loader } from 'app/features/plugins/admin/components/Loader';
|
||||
import { LdapPayload, StoreState } from 'app/types';
|
||||
|
||||
import { LdapDrawerComponent } from './LdapDrawer';
|
||||
|
||||
const appEvents = getAppEvents();
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
@ -71,6 +73,7 @@ const emptySettings: LdapPayload = {
|
||||
|
||||
export const LdapSettingsPage = () => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||
|
||||
const methods = useForm<LdapPayload>({ defaultValues: emptySettings });
|
||||
const { getValues, handleSubmit, register, reset } = methods;
|
||||
@ -161,6 +164,10 @@ export const LdapSettingsPage = () => {
|
||||
});
|
||||
return;
|
||||
}
|
||||
appEvents.publish({
|
||||
type: AppEvents.alertSuccess.name,
|
||||
payload: [t('ldap-settings-page.alert.discard-success', 'LDAP settings discarded')],
|
||||
});
|
||||
reset(payload);
|
||||
} catch (error) {
|
||||
appEvents.publish({
|
||||
@ -261,6 +268,23 @@ export const LdapSettingsPage = () => {
|
||||
{...register('settings.config.servers.0.search_base_dns', { required: true })}
|
||||
/>
|
||||
</Field>
|
||||
<Box borderColor="strong" borderStyle="solid" padding={2} width={68}>
|
||||
<Stack alignItems={'center'} direction={'row'} gap={2} justifyContent={'space-between'}>
|
||||
<Stack alignItems={'start'} direction={'column'}>
|
||||
<Text element="h2">
|
||||
<Trans i18nKey="ldap-settings-page.advanced-settings-section.title">Advanced Settings</Trans>
|
||||
</Text>
|
||||
<Text>
|
||||
<Trans i18nKey="ldap-settings-page.advanced-settings-section.subtitle">
|
||||
Mappings, extra security measures, and more.
|
||||
</Trans>
|
||||
</Text>
|
||||
</Stack>
|
||||
<Button variant="secondary" onClick={() => setIsDrawerOpen(true)}>
|
||||
<Trans i18nKey="ldap-settings-page.advanced-settings-section.edit.button">Edit</Trans>
|
||||
</Button>
|
||||
</Stack>
|
||||
</Box>
|
||||
<Box display={'flex'} gap={2} marginTop={5}>
|
||||
<Stack alignItems={'center'} gap={2}>
|
||||
<Button type={'submit'}>
|
||||
@ -276,6 +300,7 @@ export const LdapSettingsPage = () => {
|
||||
</Box>
|
||||
</section>
|
||||
)}
|
||||
{isDrawerOpen && <LdapDrawerComponent onClose={() => setIsDrawerOpen(false)} />}
|
||||
</form>
|
||||
</FormProvider>
|
||||
</Page.Contents>
|
||||
|
@ -90,7 +90,7 @@ export interface LdapServerConfig {
|
||||
group_search_filter: string;
|
||||
group_search_filter_user_attribute: string;
|
||||
host: string;
|
||||
min_tls_version: string;
|
||||
min_tls_version?: string;
|
||||
port: number;
|
||||
root_ca_cert: string;
|
||||
search_base_dns: string[];
|
||||
|
@ -984,8 +984,96 @@
|
||||
"refresh": "Refresh"
|
||||
}
|
||||
},
|
||||
"ldap-drawer": {
|
||||
"attributes-section": {
|
||||
"description": "Specify the LDAP attributes that map to the user‘s given name, surname, and email address, ensuring the application correctly retrieves and displays user information.",
|
||||
"email": {
|
||||
"label": "Email"
|
||||
},
|
||||
"label": "Attributes",
|
||||
"member-of": {
|
||||
"label": "Member Of"
|
||||
},
|
||||
"name": {
|
||||
"label": "Name"
|
||||
},
|
||||
"surname": {
|
||||
"label": "Surname"
|
||||
},
|
||||
"username": {
|
||||
"label": "Username"
|
||||
}
|
||||
},
|
||||
"extra-security-section": {
|
||||
"label": "Extra security measures",
|
||||
"min-tls-version": {
|
||||
"description": "This is the minimum TLS version allowed. Accepted values are: TLS1.2, TLS1.3.",
|
||||
"label": "Min TLS version"
|
||||
},
|
||||
"start-tls": {
|
||||
"description": "If set to true, use LDAP with STARTTLS instead of LDAPS",
|
||||
"label": "Start TLS"
|
||||
},
|
||||
"tls-ciphers": {
|
||||
"description": "List of comma- or space-separated ciphers",
|
||||
"label": "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)",
|
||||
"label": "Use SSL",
|
||||
"tooltip": "For a complete list of supported ciphers and TLS versions, refer to: {\n <TextLink style={{ fontSize: 'inherit' }} href=\"https://go.dev/src/crypto/tls/cipher_suites.go\" external>\n https://go.dev/src/crypto/tls/cipher_suites.go\n </TextLink>}"
|
||||
}
|
||||
},
|
||||
"group-mapping-section": {
|
||||
"description": "Map LDAP groups to Grafana org roles",
|
||||
"group-search-base-dns": {
|
||||
"description": "Separate by commas or spaces",
|
||||
"label": "Group search base DNS"
|
||||
},
|
||||
"group-search-filter": {
|
||||
"description": "Used to filter and identify group entries within the directory",
|
||||
"label": "Group search filter"
|
||||
},
|
||||
"group-search-filter-user-attribute": {
|
||||
"description": "Identifies users within group entries for filtering purposes",
|
||||
"label": "Group name attribute"
|
||||
},
|
||||
"label": "Group mapping",
|
||||
"skip-org-role-sync": {
|
||||
"description": "Prevent synchronizing users’ organization roles from your IdP",
|
||||
"label": "Skip organization role sync"
|
||||
}
|
||||
},
|
||||
"misc-section": {
|
||||
"allow-sign-up": {
|
||||
"descrition": "If not enabled, only existing Grafana users can log in using LDAP",
|
||||
"label": "Allow sign up"
|
||||
},
|
||||
"label": "Misc",
|
||||
"port": {
|
||||
"description": "Default port is 389 without SSL or 636 with SSL",
|
||||
"label": "Port",
|
||||
"placeholder": "389"
|
||||
},
|
||||
"timeout": {
|
||||
"description": "Timeout in seconds for the connection to the LDAP server",
|
||||
"label": "Timeout",
|
||||
"placeholder": "389"
|
||||
}
|
||||
},
|
||||
"title": "Advanced Settings"
|
||||
},
|
||||
"ldap-settings-page": {
|
||||
"advanced-settings-section": {
|
||||
"edit": {
|
||||
"button": "Edit"
|
||||
},
|
||||
"subtitle": "Mappings, extra security measures, and more.",
|
||||
"title": "Advanced Settings"
|
||||
},
|
||||
"alert": {
|
||||
"discard-success": "LDAP settings discarded",
|
||||
"error-fetching": "Error fetching LDAP settings",
|
||||
"error-saving": "Error saving LDAP settings",
|
||||
"error-update": "Error updating LDAP settings",
|
||||
|
@ -984,8 +984,96 @@
|
||||
"refresh": "Ŗęƒřęşĥ"
|
||||
}
|
||||
},
|
||||
"ldap-drawer": {
|
||||
"attributes-section": {
|
||||
"description": "Ŝpęčįƒy ŧĥę ĿĐÅP äŧŧřįþūŧęş ŧĥäŧ mäp ŧő ŧĥę ūşęř&ľşqūő;ş ģįvęʼn ʼnämę, şūřʼnämę, äʼnđ ęmäįľ äđđřęşş, ęʼnşūřįʼnģ ŧĥę äppľįčäŧįőʼn čőřřęčŧľy řęŧřįęvęş äʼnđ đįşpľäyş ūşęř įʼnƒőřmäŧįőʼn.",
|
||||
"email": {
|
||||
"label": "Ēmäįľ"
|
||||
},
|
||||
"label": "Åŧŧřįþūŧęş",
|
||||
"member-of": {
|
||||
"label": "Męmþęř ؃"
|
||||
},
|
||||
"name": {
|
||||
"label": "Ńämę"
|
||||
},
|
||||
"surname": {
|
||||
"label": "Ŝūřʼnämę"
|
||||
},
|
||||
"username": {
|
||||
"label": "Ůşęřʼnämę"
|
||||
}
|
||||
},
|
||||
"extra-security-section": {
|
||||
"label": "Ēχŧřä şęčūřįŧy męäşūřęş",
|
||||
"min-tls-version": {
|
||||
"description": "Ŧĥįş įş ŧĥę mįʼnįmūm ŦĿŜ vęřşįőʼn äľľőŵęđ. Åččępŧęđ väľūęş äřę: ŦĿŜ1.2, ŦĿŜ1.3.",
|
||||
"label": "Mįʼn ŦĿŜ vęřşįőʼn"
|
||||
},
|
||||
"start-tls": {
|
||||
"description": "Ĩƒ şęŧ ŧő ŧřūę, ūşę ĿĐÅP ŵįŧĥ ŜŦÅŖŦŦĿŜ įʼnşŧęäđ őƒ ĿĐÅPŜ",
|
||||
"label": "Ŝŧäřŧ ŦĿŜ"
|
||||
},
|
||||
"tls-ciphers": {
|
||||
"description": "Ŀįşŧ őƒ čőmmä- őř şpäčę-şępäřäŧęđ čįpĥęřş",
|
||||
"label": "ŦĿŜ čįpĥęřş",
|
||||
"placeholder": "ę.ģ. [\"ŦĿŜ_ÅĒŜ_256_ĞCM_ŜĦÅ384\"]"
|
||||
},
|
||||
"use-ssl": {
|
||||
"description": "Ŝęŧ ŧő ŧřūę įƒ ĿĐÅP şęřvęř şĥőūľđ ūşę ŦĿŜ čőʼnʼnęčŧįőʼn (ęįŧĥęř ŵįŧĥ ŜŦÅŖŦŦĿŜ őř ĿĐÅPŜ)",
|
||||
"label": "Ůşę ŜŜĿ",
|
||||
"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ĸ>}"
|
||||
}
|
||||
},
|
||||
"group-mapping-section": {
|
||||
"description": "Mäp ĿĐÅP ģřőūpş ŧő Ğřäƒäʼnä őřģ řőľęş",
|
||||
"group-search-base-dns": {
|
||||
"description": "Ŝępäřäŧę þy čőmmäş őř şpäčęş",
|
||||
"label": "Ğřőūp şęäřčĥ þäşę ĐŃŜ"
|
||||
},
|
||||
"group-search-filter": {
|
||||
"description": "Ůşęđ ŧő ƒįľŧęř äʼnđ įđęʼnŧįƒy ģřőūp ęʼnŧřįęş ŵįŧĥįʼn ŧĥę đįřęčŧőřy",
|
||||
"label": "Ğřőūp şęäřčĥ ƒįľŧęř"
|
||||
},
|
||||
"group-search-filter-user-attribute": {
|
||||
"description": "Ĩđęʼnŧįƒįęş ūşęřş ŵįŧĥįʼn ģřőūp ęʼnŧřįęş ƒőř ƒįľŧęřįʼnģ pūřpőşęş",
|
||||
"label": "Ğřőūp ʼnämę äŧŧřįþūŧę"
|
||||
},
|
||||
"label": "Ğřőūp mäppįʼnģ",
|
||||
"skip-org-role-sync": {
|
||||
"description": "Přęvęʼnŧ şyʼnčĥřőʼnįžįʼnģ ūşęřş’ őřģäʼnįžäŧįőʼn řőľęş ƒřőm yőūř ĨđP",
|
||||
"label": "Ŝĸįp őřģäʼnįžäŧįőʼn řőľę şyʼnč"
|
||||
}
|
||||
},
|
||||
"misc-section": {
|
||||
"allow-sign-up": {
|
||||
"descrition": "Ĩƒ ʼnőŧ ęʼnäþľęđ, őʼnľy ęχįşŧįʼnģ Ğřäƒäʼnä ūşęřş čäʼn ľőģ įʼn ūşįʼnģ ĿĐÅP",
|
||||
"label": "Åľľőŵ şįģʼn ūp"
|
||||
},
|
||||
"label": "Mįşč",
|
||||
"port": {
|
||||
"description": "Đęƒäūľŧ pőřŧ įş 389 ŵįŧĥőūŧ ŜŜĿ őř 636 ŵįŧĥ ŜŜĿ",
|
||||
"label": "Pőřŧ",
|
||||
"placeholder": "389"
|
||||
},
|
||||
"timeout": {
|
||||
"description": "Ŧįmęőūŧ įʼn şęčőʼnđş ƒőř ŧĥę čőʼnʼnęčŧįőʼn ŧő ŧĥę ĿĐÅP şęřvęř",
|
||||
"label": "Ŧįmęőūŧ",
|
||||
"placeholder": "389"
|
||||
}
|
||||
},
|
||||
"title": "Åđväʼnčęđ Ŝęŧŧįʼnģş"
|
||||
},
|
||||
"ldap-settings-page": {
|
||||
"advanced-settings-section": {
|
||||
"edit": {
|
||||
"button": "Ēđįŧ"
|
||||
},
|
||||
"subtitle": "Mäppįʼnģş, ęχŧřä şęčūřįŧy męäşūřęş, äʼnđ mőřę.",
|
||||
"title": "Åđväʼnčęđ Ŝęŧŧįʼnģş"
|
||||
},
|
||||
"alert": {
|
||||
"discard-success": "ĿĐÅP şęŧŧįʼnģş đįşčäřđęđ",
|
||||
"error-fetching": "Ēřřőř ƒęŧčĥįʼnģ ĿĐÅP şęŧŧįʼnģş",
|
||||
"error-saving": "Ēřřőř şävįʼnģ ĿĐÅP şęŧŧįʼnģş",
|
||||
"error-update": "Ēřřőř ūpđäŧįʼnģ ĿĐÅP şęŧŧįʼnģş",
|
||||
|
Loading…
Reference in New Issue
Block a user