mirror of
https://github.com/Graylog2/graylog2-server.git
synced 2026-03-13 09:32:21 +08:00
Add auth service config setting for user's default time zone (#24381)
* Add auth service config setting for user's default time zone
The authentication backends for Active Directory, LDAP, OIDC, Okta, and SAML
previously set the time zone for +newly synchronized users to the value of
the `root_timezone` config file setting. ("UTC" by default)
This change introduces a configurable "default user time zone" setting for
all authentication backends. The default value is unset, meaning that the
browser's time zone will be used by default.
Other changes:
- Adjust the notification text for AD/LDAP configurations to reflect
reality. Default roles are only set for new users, not on login.
- Add note to UPGRADING.md
* Add changelog entry
* Remove unneeded default-user-timezone-select class
* Show "Browser's time zone" when no zone is selected
This commit is contained in:
10
UPGRADING.md
10
UPGRADING.md
@@ -1,12 +1,20 @@
|
||||
Upgrading to Graylog 7.1.x
|
||||
==========================
|
||||
|
||||
## User Session Termination
|
||||
|
||||
All user sessions will be terminated when upgrading because the internal storage format for sessions has been changed.
|
||||
Users will have to log in again.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
tbd
|
||||
### External Authentication Services: Changed Default User Time Zone
|
||||
|
||||
The authentication backends for Active Directory, LDAP, OIDC, Okta, and SAML previously set the time zone for
|
||||
newly synchronized users to the value of the `root_timezone` config file setting. ("UTC" by default)
|
||||
|
||||
Graylog 7.1 introduces a configurable "default user time zone" setting for all authentication backends.
|
||||
The default value is unset, meaning that the browser's time zone will be used by default.
|
||||
|
||||
## Configuration File Changes
|
||||
|
||||
|
||||
4
changelog/unreleased/pr-24381.toml
Normal file
4
changelog/unreleased/pr-24381.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
type = "c"
|
||||
message = "Add auth service config setting for user's default time zone. (see upgrade notes)"
|
||||
|
||||
pulls = ["24381", "graylog-plugin-enterprise#12641"]
|
||||
@@ -29,7 +29,9 @@ import org.mongojack.Id;
|
||||
import org.mongojack.ObjectId;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
@@ -42,6 +44,7 @@ public abstract class AuthServiceBackendDTO implements BuildableMongoEntity<Auth
|
||||
public static final String FIELD_TITLE = "title";
|
||||
public static final String FIELD_DESCRIPTION = "description";
|
||||
private static final String FIELD_DEFAULT_ROLES = "default_roles";
|
||||
private static final String FIELD_DEFAULT_USER_TIMEZONE = "default_user_timezone";
|
||||
private static final String FIELD_CONFIG = "config";
|
||||
|
||||
@Id
|
||||
@@ -59,6 +62,9 @@ public abstract class AuthServiceBackendDTO implements BuildableMongoEntity<Auth
|
||||
@JsonProperty(FIELD_DEFAULT_ROLES)
|
||||
public abstract Set<String> defaultRoles();
|
||||
|
||||
@JsonProperty(FIELD_DEFAULT_USER_TIMEZONE)
|
||||
public abstract Optional<ZoneId> defaultUserTimezone();
|
||||
|
||||
@NotNull
|
||||
@JsonProperty(FIELD_CONFIG)
|
||||
public abstract AuthServiceBackendConfig config();
|
||||
@@ -96,7 +102,8 @@ public abstract class AuthServiceBackendDTO implements BuildableMongoEntity<Auth
|
||||
public static Builder create() {
|
||||
return new AutoValue_AuthServiceBackendDTO.Builder()
|
||||
.description("")
|
||||
.defaultRoles(Collections.emptySet());
|
||||
.defaultRoles(Collections.emptySet())
|
||||
.defaultUserTimezone(null);
|
||||
}
|
||||
|
||||
@Id
|
||||
@@ -113,6 +120,9 @@ public abstract class AuthServiceBackendDTO implements BuildableMongoEntity<Auth
|
||||
@JsonProperty(FIELD_DEFAULT_ROLES)
|
||||
public abstract Builder defaultRoles(Set<String> defaultRoles);
|
||||
|
||||
@JsonProperty(FIELD_DEFAULT_USER_TIMEZONE)
|
||||
public abstract Builder defaultUserTimezone(@Nullable ZoneId defaultUserTimezone);
|
||||
|
||||
@JsonProperty(FIELD_CONFIG)
|
||||
public abstract Builder config(AuthServiceBackendConfig config);
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package org.graylog.security.authservice;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import org.graylog2.plugin.database.ValidationException;
|
||||
import org.graylog2.plugin.database.users.User;
|
||||
import org.graylog2.shared.users.UserService;
|
||||
@@ -25,9 +26,6 @@ import org.joda.time.DateTimeZone;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -35,15 +33,12 @@ public class ProvisionerService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ProvisionerService.class);
|
||||
|
||||
private final UserService userService;
|
||||
private final DateTimeZone rootTimeZone;
|
||||
private final Map<String, ProvisionerAction.Factory<? extends ProvisionerAction>> provisionerActionFactories;
|
||||
|
||||
@Inject
|
||||
public ProvisionerService(UserService userService,
|
||||
@Named("root_timezone") DateTimeZone rootTimeZone,
|
||||
Map<String, ProvisionerAction.Factory<? extends ProvisionerAction>> provisionerActionFactories) {
|
||||
this.userService = userService;
|
||||
this.rootTimeZone = rootTimeZone;
|
||||
this.provisionerActionFactories = provisionerActionFactories;
|
||||
}
|
||||
|
||||
@@ -142,8 +137,10 @@ public class ProvisionerService {
|
||||
// Set fields there that should not be overridden by the authentication service provisioning
|
||||
user.setRoleIds(userDetails.defaultRoles());
|
||||
user.setPermissions(Collections.emptyList());
|
||||
// TODO: Does the timezone need to be configurable per auth service backend?
|
||||
user.setTimeZone(rootTimeZone);
|
||||
// Default to null for the user's time zone so the UI will use the browser's time zone by default.
|
||||
user.setTimeZone(userDetails.timezone()
|
||||
.map(zoneId -> DateTimeZone.forID(zoneId.getId()))
|
||||
.orElse(null));
|
||||
// TODO: Does the session timeout need to be configurable per auth service backend?
|
||||
user.setSessionTimeoutMs(UserConfiguration.DEFAULT_VALUES.globalSessionTimeoutInterval().toMillis());
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -46,6 +47,8 @@ public abstract class UserDetails {
|
||||
|
||||
public abstract Optional<String> lastName();
|
||||
|
||||
public abstract Optional<ZoneId> timezone();
|
||||
|
||||
/**
|
||||
* Some authentication backends only currently support the fullName attribute (and not firstName and lastName),
|
||||
* so it is still optionally available here. Prefer use of only firstName and lastName when available.
|
||||
@@ -98,6 +101,8 @@ public abstract class UserDetails {
|
||||
|
||||
public abstract Builder lastName(@Nullable String lastName);
|
||||
|
||||
public abstract Builder timezone(@Nullable ZoneId timezone);
|
||||
|
||||
/**
|
||||
* Starting in Graylog 4.1, use of this method is deprecated.
|
||||
* Prefer use of the {@link #firstName()} and {@link #lastName()} methods instead when possible. This way,
|
||||
@@ -119,7 +124,7 @@ public abstract class UserDetails {
|
||||
|
||||
// Either a fullName, or a firstName/lastName are required.
|
||||
final boolean missingFirstOrLast = !userDetails.firstName().isPresent()
|
||||
|| !userDetails.lastName().isPresent();
|
||||
|| !userDetails.lastName().isPresent();
|
||||
|
||||
if (missingFirstOrLast && !userDetails.fullName().isPresent()) {
|
||||
throw new IllegalArgumentException("Either a firstName/lastName or a fullName are required.");
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.google.inject.assistedinject.Assisted;
|
||||
import com.unboundid.ldap.sdk.Filter;
|
||||
import com.unboundid.ldap.sdk.LDAPConnection;
|
||||
import com.unboundid.ldap.sdk.LDAPException;
|
||||
import jakarta.inject.Inject;
|
||||
import org.graylog.security.authservice.AuthServiceBackend;
|
||||
import org.graylog.security.authservice.AuthServiceBackendDTO;
|
||||
import org.graylog.security.authservice.AuthServiceCredentials;
|
||||
@@ -39,9 +40,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -122,6 +120,7 @@ public class ADAuthServiceBackend implements AuthServiceBackend {
|
||||
.fullName(userEntry.fullName())
|
||||
.email(userEntry.email())
|
||||
.defaultRoles(backend.defaultRoles())
|
||||
.timezone(backend.defaultUserTimezone().orElse(null))
|
||||
.build());
|
||||
|
||||
return Optional.of(AuthenticationDetails.builder().userDetails(userDetails).build());
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.unboundid.ldap.sdk.LDAPConnection;
|
||||
import com.unboundid.ldap.sdk.LDAPException;
|
||||
import jakarta.inject.Inject;
|
||||
import org.graylog.security.authservice.AuthServiceBackend;
|
||||
import org.graylog.security.authservice.AuthServiceBackendDTO;
|
||||
import org.graylog.security.authservice.AuthServiceCredentials;
|
||||
@@ -38,9 +39,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -102,6 +100,7 @@ public class LDAPAuthServiceBackend implements AuthServiceBackend {
|
||||
.fullName(userEntry.fullName())
|
||||
.email(userEntry.email())
|
||||
.defaultRoles(backend.defaultRoles())
|
||||
.timezone(backend.defaultUserTimezone().orElse(null))
|
||||
.build());
|
||||
|
||||
return Optional.of(AuthenticationDetails.builder().userDetails(userDetails).build());
|
||||
|
||||
@@ -35,6 +35,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -64,7 +65,7 @@ public class ProvisionerServiceTest {
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
provisionerService = new ProvisionerService(userService, DateTimeZone.UTC, new HashMap<>());
|
||||
provisionerService = new ProvisionerService(userService, new HashMap<>());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -90,6 +91,7 @@ public class ProvisionerServiceTest {
|
||||
provisionerService.provision(userDetails);
|
||||
verify(userService, times(1)).save(isA(User.class));
|
||||
verify(user, times(1)).setFirstLastFullNames(eq(FIRST_NAME), eq(LAST_NAME));
|
||||
verify(user, times(1)).setTimeZone((DateTimeZone) isNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -114,5 +116,6 @@ public class ProvisionerServiceTest {
|
||||
provisionerService.provision(userDetails);
|
||||
verify(userService, times(1)).save(isA(User.class));
|
||||
verify(user, times(1)).setFullName(FULL_NAME);
|
||||
verify(user, times(1)).setTimeZone((DateTimeZone) isNull());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ const UserSyncSection = ({ authenticationBackend, roles, excludedFields = {} }:
|
||||
userUniqueIdAttribute,
|
||||
emailAttributes,
|
||||
} = authenticationBackend.config;
|
||||
const { defaultRoles = Immutable.List() } = authenticationBackend;
|
||||
const { defaultRoles = Immutable.List(), defaultUserTimezone } = authenticationBackend;
|
||||
|
||||
return (
|
||||
<SectionComponent
|
||||
@@ -66,6 +66,7 @@ const UserSyncSection = ({ authenticationBackend, roles, excludedFields = {} }:
|
||||
<ReadOnlyFormGroup label="ID Attribute" value={userUniqueIdAttribute} />
|
||||
)}
|
||||
<ReadOnlyFormGroup label="Default Roles" value={rolesList(defaultRoles, roles)} />
|
||||
<ReadOnlyFormGroup label="Default User Time Zone" value={defaultUserTimezone || "Browser's time zone"} />
|
||||
</SectionComponent>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -115,6 +115,7 @@ const _prepareSubmitPayload =
|
||||
const formValues = overrideFormValues ?? getUpdatedFormsValues();
|
||||
const {
|
||||
defaultRoles = '',
|
||||
defaultUserTimezone,
|
||||
description,
|
||||
serverHost,
|
||||
serverPort,
|
||||
@@ -136,6 +137,7 @@ const _prepareSubmitPayload =
|
||||
title,
|
||||
description,
|
||||
default_roles: defaultRoles.split(','),
|
||||
default_user_timezone: defaultUserTimezone,
|
||||
config: {
|
||||
servers: [{ host: serverHost, port: serverPort }],
|
||||
system_user_dn: systemUserDn,
|
||||
|
||||
@@ -23,6 +23,7 @@ export type WizardFormValues = {
|
||||
title?: string;
|
||||
description?: string;
|
||||
defaultRoles?: string;
|
||||
defaultUserTimezone?: string;
|
||||
groupSearchBase?: string;
|
||||
groupSearchPattern?: string;
|
||||
serverHost?: string;
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||
*/
|
||||
import * as React from 'react';
|
||||
import type * as Immutable from 'immutable';
|
||||
import { useContext } from 'react';
|
||||
import type * as Immutable from 'immutable';
|
||||
import type { FormikProps } from 'formik';
|
||||
import { Formik, Form, Field } from 'formik';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import type Role from 'logic/roles/Role';
|
||||
import { validateField, formHasErrors } from 'util/FormsUtils';
|
||||
import { FormikFormGroup, Select, InputList } from 'components/common';
|
||||
import { FormikFormGroup, Select, InputList, TimezoneSelect } from 'components/common';
|
||||
import { Alert, Button, ButtonToolbar, Row, Col, Panel, Input } from 'components/bootstrap';
|
||||
import { getPathnameWithoutId } from 'util/URLUtils';
|
||||
import useSendTelemetry from 'logic/telemetry/useSendTelemetry';
|
||||
@@ -38,6 +38,7 @@ export const STEP_KEY = 'user-synchronization';
|
||||
// to be able to associate backend validation errors with the form
|
||||
export const FORM_VALIDATION = {
|
||||
defaultRoles: { required: true },
|
||||
defaultUserTimezone: {},
|
||||
userFullNameAttribute: { required: true },
|
||||
userNameAttribute: { required: true },
|
||||
emailAttributes: {},
|
||||
@@ -180,9 +181,8 @@ const UserSyncStep = ({
|
||||
<Row>
|
||||
<Col sm={9} smOffset={3}>
|
||||
<Panel bsStyle="info">
|
||||
Changing the static role assignment will only affect new users created via{' '}
|
||||
{stepsState.authBackendMeta.serviceTitle}! Existing user accounts will be updated on their next login,
|
||||
or if you edit their roles manually.
|
||||
Changing the default role and time zone assignments will only affect new users created via{' '}
|
||||
{stepsState.authBackendMeta.serviceTitle}!
|
||||
</Panel>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -209,6 +209,23 @@ const UserSyncStep = ({
|
||||
)}
|
||||
</Field>
|
||||
|
||||
<Field name="defaultUserTimezone">
|
||||
{({ field: { name, value, onChange } }) => (
|
||||
<Input
|
||||
id="default-user-timezone-select"
|
||||
help={help.defaultUserTimezone}
|
||||
label="Default User Time Zone"
|
||||
labelClassName="col-sm-3"
|
||||
wrapperClassName="col-sm-9">
|
||||
<TimezoneSelect
|
||||
value={value || "Browser's time zone"}
|
||||
name="timezone"
|
||||
onChange={(newValue) => onChange({ target: { name, value: newValue } })}
|
||||
/>
|
||||
</Input>
|
||||
)}
|
||||
</Field>
|
||||
|
||||
<Row>
|
||||
<Col sm={9} smOffset={3}>
|
||||
<Alert bsStyle="info">
|
||||
|
||||
@@ -24,6 +24,7 @@ export default ({
|
||||
title,
|
||||
description,
|
||||
defaultRoles = Immutable.List(),
|
||||
defaultUserTimezone,
|
||||
config: {
|
||||
servers = [],
|
||||
systemUserDn,
|
||||
@@ -40,6 +41,7 @@ export default ({
|
||||
title,
|
||||
description,
|
||||
defaultRoles: defaultRoles.join(),
|
||||
defaultUserTimezone: defaultUserTimezone,
|
||||
serverHost: servers[0].host,
|
||||
serverPort: servers[0].port,
|
||||
systemUserDn,
|
||||
|
||||
@@ -67,6 +67,7 @@ export const HELP = {
|
||||
interface
|
||||
</span>
|
||||
),
|
||||
defaultUserTimezone: <span>Choose the default time zone for new users.</span>,
|
||||
};
|
||||
|
||||
export const AUTH_BACKEND_META = {
|
||||
|
||||
@@ -73,6 +73,7 @@ export const HELP = {
|
||||
interface
|
||||
</span>
|
||||
),
|
||||
defaultUserTimezone: <span>Choose the default time zone for new users.</span>,
|
||||
emailAttributes: (
|
||||
<span>
|
||||
Which LDAP attribute to use for the user's email address, e.g. <code>mail</code>.<br />
|
||||
|
||||
@@ -26,6 +26,7 @@ type InternalState = {
|
||||
title: string;
|
||||
description: string;
|
||||
defaultRoles: Immutable.List<string>;
|
||||
defaultUserTimezone: string;
|
||||
config: DirectoryServiceBackendConfig | OktaBackendConfig;
|
||||
};
|
||||
|
||||
@@ -38,6 +39,7 @@ export type AuthenticationBackendJSON = {
|
||||
title: string;
|
||||
description: string;
|
||||
default_roles: Array<string>;
|
||||
default_user_timezone: string;
|
||||
config: DirectoryServiceBackendConfig | OktaBackendConfig;
|
||||
};
|
||||
|
||||
@@ -69,6 +71,7 @@ export default class AuthenticationBackend {
|
||||
title: InternalState['title'],
|
||||
description: InternalState['description'],
|
||||
defaultRoles: InternalState['defaultRoles'],
|
||||
defaultUserTimezone: InternalState['defaultUserTimezone'],
|
||||
config: InternalState['config'],
|
||||
) {
|
||||
this._value = {
|
||||
@@ -76,6 +79,7 @@ export default class AuthenticationBackend {
|
||||
title,
|
||||
description,
|
||||
defaultRoles,
|
||||
defaultUserTimezone,
|
||||
config,
|
||||
};
|
||||
}
|
||||
@@ -96,12 +100,16 @@ export default class AuthenticationBackend {
|
||||
return this._value.defaultRoles;
|
||||
}
|
||||
|
||||
get defaultUserTimezone(): InternalState['defaultUserTimezone'] {
|
||||
return this._value.defaultUserTimezone;
|
||||
}
|
||||
|
||||
get config(): InternalState['config'] {
|
||||
return this._value.config;
|
||||
}
|
||||
|
||||
toBuilder(): Builder {
|
||||
const { id, title, description, defaultRoles, config } = this._value;
|
||||
const { id, title, description, defaultRoles, defaultUserTimezone, config } = this._value;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
return new Builder(
|
||||
@@ -110,13 +118,14 @@ export default class AuthenticationBackend {
|
||||
title,
|
||||
description,
|
||||
defaultRoles,
|
||||
defaultUserTimezone,
|
||||
config,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
const { id, title, description, defaultRoles = Immutable.List(), config } = this._value;
|
||||
const { id, title, description, defaultRoles = Immutable.List(), defaultUserTimezone, config } = this._value;
|
||||
|
||||
const formattedConfig = configToJson(config);
|
||||
|
||||
@@ -125,16 +134,31 @@ export default class AuthenticationBackend {
|
||||
title,
|
||||
description,
|
||||
default_roles: defaultRoles.toJS(),
|
||||
default_user_timezone: defaultUserTimezone,
|
||||
config: formattedConfig,
|
||||
};
|
||||
}
|
||||
|
||||
static fromJSON(value: AuthenticationBackendJSON) {
|
||||
const { id, title, description, default_roles: defaultRoles, config } = value;
|
||||
const {
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
default_roles: defaultRoles,
|
||||
default_user_timezone: defaultUserTimezone,
|
||||
config,
|
||||
} = value;
|
||||
|
||||
const formattedConfig = configFromJson(config);
|
||||
|
||||
return new AuthenticationBackend(id, title, description, Immutable.List(defaultRoles), formattedConfig);
|
||||
return new AuthenticationBackend(
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
Immutable.List(defaultRoles),
|
||||
defaultUserTimezone,
|
||||
formattedConfig,
|
||||
);
|
||||
}
|
||||
|
||||
static builder(): Builder {
|
||||
@@ -173,8 +197,8 @@ class Builder {
|
||||
}
|
||||
|
||||
build(): AuthenticationBackend {
|
||||
const { id, title, description, defaultRoles, config } = this.value.toObject();
|
||||
const { id, title, description, defaultRoles, defaultUserTimezone, config } = this.value.toObject();
|
||||
|
||||
return new AuthenticationBackend(id, title, description, defaultRoles, config);
|
||||
return new AuthenticationBackend(id, title, description, defaultRoles, defaultUserTimezone, config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ export type DirectoryServiceBackendConfigJson = {
|
||||
export type DirectoryServiceBackend = {
|
||||
id: AuthenticationBackend['id'];
|
||||
defaultRoles: AuthenticationBackend['defaultRoles'];
|
||||
defaultUserTimezone: AuthenticationBackend['defaultUserTimezone'];
|
||||
title: AuthenticationBackend['title'];
|
||||
description: AuthenticationBackend['description'];
|
||||
config: DirectoryServiceBackendConfig;
|
||||
@@ -62,6 +63,7 @@ export type WizardSubmitPayload = {
|
||||
title: AuthenticationBackendJSON['title'];
|
||||
description: AuthenticationBackendJSON['description'];
|
||||
default_roles: AuthenticationBackendJSON['default_roles'];
|
||||
default_user_timezone: AuthenticationBackendJSON['default_user_timezone'];
|
||||
config: DirectoryServiceBackendConfigJson & {
|
||||
system_user_password:
|
||||
| (string | { keep_value: true } | { delete_value: true } | { set_value: string | undefined })
|
||||
|
||||
@@ -109,6 +109,8 @@ export interface SharedBackendProps {
|
||||
|
||||
defaultRoles: AuthenticationBackend['defaultRoles'];
|
||||
|
||||
defaultUserTimezone: AuthenticationBackend['defaultUserTimezone'];
|
||||
|
||||
title: AuthenticationBackend['title'];
|
||||
|
||||
description: AuthenticationBackend['description'];
|
||||
|
||||
Reference in New Issue
Block a user