From ecd65b3ce7bf48f8b9bd19b9b9f87014c72c1aeb Mon Sep 17 00:00:00 2001 From: Jenny <32821331+jenny-s51@users.noreply.github.com> Date: Wed, 23 Feb 2022 09:46:56 -0500 Subject: [PATCH] Username field (#2135) --- cypress/integration/users_test.spec.ts | 2 +- src/realm-settings/LoginTab.tsx | 44 ++++++++++++++++++- src/realm-settings/help.ts | 2 + src/realm-settings/messages.ts | 4 ++ src/realm-settings/realm-settings-section.css | 18 +++++--- src/user/UserForm.tsx | 29 +++++++++--- src/user/UsersTabs.tsx | 6 ++- 7 files changed, 87 insertions(+), 18 deletions(-) diff --git a/cypress/integration/users_test.spec.ts b/cypress/integration/users_test.spec.ts index 6538305cd0..ff02b13b1c 100644 --- a/cypress/integration/users_test.spec.ts +++ b/cypress/integration/users_test.spec.ts @@ -178,7 +178,7 @@ describe("User creation", () => { // Go to user groups userGroupsPage.goToGroupsTab(); cy.findByTestId(`leave-${groupsList[0]}`).click(); - cy.findByTestId("confirm").click(); + cy.findByTestId("confirm").click({ force: true }); }); it("Go to user consents test", () => { diff --git a/src/realm-settings/LoginTab.tsx b/src/realm-settings/LoginTab.tsx index 15f772af2d..326b249418 100644 --- a/src/realm-settings/LoginTab.tsx +++ b/src/realm-settings/LoginTab.tsx @@ -34,7 +34,10 @@ export const RealmSettingsLoginTab = ({ return ( - + - + + + + + } + hasNoPaddingTop + > + ( + { + updateSwitchValue(onChange, value, "editUsernameAllowed"); + }} + /> + )} + /> + + + ); }; diff --git a/src/realm-settings/help.ts b/src/realm-settings/help.ts index 73f1730b30..c52889d19a 100644 --- a/src/realm-settings/help.ts +++ b/src/realm-settings/help.ts @@ -146,5 +146,7 @@ export default { "The condition is checked during client registration/update requests and it evaluates to true if the entity (usually user), who is creating/updating client is member of the specified role. For reference the realm role, you can use the realm role name like 'my_realm_role' . For reference client role, you can use the client_id.role_name for example 'my_client.my_client_role' will refer to client role 'my_client_role' of client 'my_client'. ", defaultGroups: "Default groups allow you to automatically assign groups membership whenever any new user is created or imported through <1>identity brokering.", + editUsername: + "If enabled, the username field is editable, readonly otherwise.", }, }; diff --git a/src/realm-settings/messages.ts b/src/realm-settings/messages.ts index 81a3bff91c..afba9de389 100644 --- a/src/realm-settings/messages.ts +++ b/src/realm-settings/messages.ts @@ -102,6 +102,7 @@ export default { noKeys: "No keys", noKeysDescription: "You haven't created any ", certificate: "Certificate", + loginScreenCustomization: "Login screen customization", userRegistration: "User registration", userRegistrationHelpText: "Enable/disable the registration page. A link for registration will show on login page too.", @@ -111,6 +112,7 @@ export default { rememberMe: "Remember me", rememberMeHelpText: "Show checkbox on login page to allow user to remain logged in between browser restarts until session expires.", + emailSettings: "Email settings", emailAsUsername: "Email as username", emailAsUsernameHelpText: "Allow users to set email as username.", loginWithEmail: "Login with email", @@ -124,6 +126,8 @@ export default { verifyEmail: "Verify email", verifyEmailHelpText: "Require user to verify their email address after initial login or after address changes are submitted.", + userInfoSettings: "User info settings", + editUsername: "Edit username", testConnection: "Test connection", testConnectionSuccess: "Success! SMTP connection successful. E-mail was sent!", diff --git a/src/realm-settings/realm-settings-section.css b/src/realm-settings/realm-settings-section.css index 34c83f9f21..2035de3202 100644 --- a/src/realm-settings/realm-settings-section.css +++ b/src/realm-settings/realm-settings-section.css @@ -1,5 +1,6 @@ .pf-c-card.pf-m-flat.kc-login-screen, .pf-c-card.pf-m-flat.kc-email-settings, +.pf-c-card.pf-m-flat.kc-user-info-settings, .pf-c-card.pf-m-flat.kc-email-template, .pf-c-card.pf-m-flat.kc-email-connection, .pf-c-card.pf-m-flat.kc-message-bundles, @@ -24,14 +25,16 @@ article.pf-c-card.pf-m-flat.kc-email-connection } .kc-login-screen > div.pf-c-card__header.kc-form-panel__header, -.kc-email-settings > div.pf-c-card__header.kc-form-panel__header { +.kc-email-settings > div.pf-c-card__header.kc-form-panel__header, +.kc-user-info-settings > div.pf-c-card__header.kc-form-panel__header { padding-bottom: 0px; padding-left: 0px; padding-top: 0px; } .kc-email-settings > div.pf-c-card__body.kc-form-panel__body, -.kc-login-screen > div.pf-c-card__body.kc-form-panel__body { +.kc-login-screen > div.pf-c-card__body.kc-form-panel__body, +.kc-user-info-settings > div.pf-c-card__body.kc-form-panel__body { padding-left: 0px; padding-bottom: var(--pf-global--spacer--2xl); } @@ -219,7 +222,8 @@ article.pf-c-card.pf-m-flat.kc-login-settings-template padding: 0 var(--pf-global--spacer--md) 0 var(--pf-global--spacer--md); } -.kc-backToPolicies, .kc-backToPolicies { +.kc-backToPolicies, +.kc-backToPolicies { width: 5rem; } @@ -228,20 +232,20 @@ article.pf-c-card.pf-m-flat.kc-login-settings-template } .kc-executor-trash-icon { - margin-left: .5rem; + margin-left: 0.5rem; color: var(--pf-global--Color--200); } .kc-executor-trash-icon:hover { filter: brightness(55%); -} +} .kc-condition-link { margin-right: 0.625rem; } .kc-conditionType-trash-icon { - margin-left: .5rem; + margin-left: 0.5rem; color: var(--pf-global--Color--400); } @@ -255,7 +259,7 @@ article.pf-c-card.pf-m-flat.kc-login-settings-template input#kc-scopes { width: 630px; - + margin-right: 24px; } diff --git a/src/user/UserForm.tsx b/src/user/UserForm.tsx index 7b854b4d74..9b1e974a34 100644 --- a/src/user/UserForm.tsx +++ b/src/user/UserForm.tsx @@ -20,12 +20,13 @@ import { FormAccess } from "../components/form-access/FormAccess"; import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation"; import { HelpItem } from "../components/help-enabler/HelpItem"; import { useRealm } from "../context/realm-context/RealmContext"; -import { useAdminClient } from "../context/auth/AdminClient"; +import { useAdminClient, useFetch } from "../context/auth/AdminClient"; import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation"; import { useAlerts } from "../components/alert/Alerts"; import { emailRegexPattern } from "../util"; import { GroupPickerDialog } from "../components/group/GroupPickerDialog"; import moment from "moment"; +import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation"; export type BruteForced = { isBruteForceProtected?: boolean; @@ -49,7 +50,7 @@ export const UserForm = ({ onGroupsUpdate, }: UserFormProps) => { const { t } = useTranslation("users"); - const { realm } = useRealm(); + const { realm: realmName } = useRealm(); const [ isRequiredUserActionsDropdownOpen, @@ -67,6 +68,21 @@ export const UserForm = ({ ); const [open, setOpen] = useState(false); const [locked, setLocked] = useState(isLocked); + const [realm, setRealm] = useState(); + + useFetch( + async () => { + const realm = await adminClient.realms.findOne({ realm: realmName }); + if (!realm) { + throw new Error(t("common:notFound")); + } + return realm; + }, + (realm) => { + setRealm(realm); + }, + [] + ); const unLockUser = async () => { try { @@ -148,7 +164,7 @@ export const UserForm = ({ filterGroups={selectedGroups.map((group) => group.name!)} /> )} - {user?.id ? ( + {user?.id && ( <> @@ -165,7 +181,8 @@ export const UserForm = ({ /> - ) : ( + )} + {!realm?.registrationEmailAsUsername && ( )} @@ -401,7 +418,7 @@ export const UserForm = ({