Improve flow for testing e-mail server settings (#3619)
This commit is contained in:
parent
c56f9b4132
commit
1de4d24593
8 changed files with 356 additions and 416 deletions
|
@ -78,7 +78,15 @@ describe("Realm settings tabs tests", () => {
|
|||
});
|
||||
|
||||
it("Go to email tab", () => {
|
||||
const msg: string = "Error! Failed to send email.";
|
||||
// Configure an e-mail address so we can test the connection settings.
|
||||
cy.wrap(null).then(async () => {
|
||||
const adminUser = await adminClient.getAdminUser();
|
||||
|
||||
await adminClient.updateUser(adminUser.id!, {
|
||||
email: "admin@example.com",
|
||||
});
|
||||
});
|
||||
|
||||
sidebarPage.goToRealmSettings();
|
||||
cy.findByTestId("rs-email-tab").click();
|
||||
//required fields not filled in or not filled properly
|
||||
|
@ -100,17 +108,10 @@ describe("Realm settings tabs tests", () => {
|
|||
realmSettingsPage.toggleCheck(realmSettingsPage.enableSslCheck);
|
||||
realmSettingsPage.toggleCheck(realmSettingsPage.enableStartTlsCheck);
|
||||
realmSettingsPage.fillHostField("localhost");
|
||||
cy.intercept(`/admin/realms/${realmName}/users/*`).as("load");
|
||||
|
||||
cy.findByTestId(realmSettingsPage.testConnectionButton).click();
|
||||
cy.wait("@load");
|
||||
|
||||
//ln109-113 cause the tests to fail locally, but is needed for the test to pass on the dashboard.
|
||||
realmSettingsPage.fillEmailField(
|
||||
"example" + (Math.random() + 1).toString(36).substring(7) + "@example.com"
|
||||
);
|
||||
cy.findByTestId(realmSettingsPage.modalTestConnectionButton).click();
|
||||
|
||||
masthead.checkNotificationMessage(msg, true);
|
||||
masthead.checkNotificationMessage("Error! Failed to send email", true);
|
||||
});
|
||||
|
||||
it("Go to themes tab", () => {
|
||||
|
|
|
@ -4,11 +4,16 @@ export default class Masthead extends CommonElements {
|
|||
private helpBtn = "#help";
|
||||
private closeAlertMessageBtn = ".pf-c-alert__action button";
|
||||
private closeLastAlertMessageBtn =
|
||||
".pf-c-alert-group > li:first-child .pf-c-alert__action button";
|
||||
"li:first-child .pf-c-alert__action button";
|
||||
|
||||
private alertMessage = ".pf-c-alert__title";
|
||||
private userDrpDwn = "#user-dropdown";
|
||||
private userDrpDwnKebab = "#user-dropdown-kebab";
|
||||
private globalAlerts = "global-alerts";
|
||||
|
||||
private getAlertsContainer() {
|
||||
return cy.findByTestId(this.globalAlerts);
|
||||
}
|
||||
|
||||
checkIsAdminConsole() {
|
||||
cy.get(this.logoBtn).should("exist");
|
||||
|
@ -50,10 +55,13 @@ export default class Masthead extends CommonElements {
|
|||
}
|
||||
|
||||
checkNotificationMessage(message: string, closeNotification = true) {
|
||||
cy.get(this.alertMessage).should("contain.text", message);
|
||||
this.getAlertsContainer()
|
||||
.find(this.alertMessage)
|
||||
.should("contain.text", message);
|
||||
|
||||
if (closeNotification) {
|
||||
cy.get(`button[title="` + message.replaceAll('"', '\\"') + `"]`)
|
||||
this.getAlertsContainer()
|
||||
.find(`button[title="` + message.replaceAll('"', '\\"') + `"]`)
|
||||
.last()
|
||||
.click({ force: true });
|
||||
}
|
||||
|
@ -61,14 +69,16 @@ export default class Masthead extends CommonElements {
|
|||
}
|
||||
|
||||
closeLastAlertMessage() {
|
||||
cy.get(this.closeLastAlertMessageBtn).click();
|
||||
this.getAlertsContainer().find(this.closeLastAlertMessageBtn).click();
|
||||
return this;
|
||||
}
|
||||
|
||||
closeAllAlertMessages() {
|
||||
cy.get(this.closeAlertMessageBtn).each(() => {
|
||||
cy.get(this.closeAlertMessageBtn).click({ force: true, multiple: true });
|
||||
this.getAlertsContainer().find(this.closeAlertMessageBtn).click({
|
||||
force: true,
|
||||
multiple: true,
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -98,6 +98,17 @@ class AdminClient {
|
|||
return await this.client.users.create(user);
|
||||
}
|
||||
|
||||
async updateUser(id: string, payload: UserRepresentation) {
|
||||
await this.login();
|
||||
return this.client.users.update({ id }, payload);
|
||||
}
|
||||
|
||||
async getAdminUser() {
|
||||
await this.login();
|
||||
const [user] = await this.client.users.find({ username: "admin" });
|
||||
return user;
|
||||
}
|
||||
|
||||
async addUserToGroup(userId: string, groupId: string) {
|
||||
await this.login();
|
||||
await this.client.users.addToGroup({ id: userId, groupId });
|
||||
|
|
|
@ -114,8 +114,6 @@
|
|||
"loginWithEmailHelpText": "Allow users to log in with their email address.",
|
||||
"duplicateEmailsAllowed": "Duplicate emails",
|
||||
"duplicateEmailsHelpText": "Allow multiple users to have the same email address. Changing this setting will also clear the user's cache. It is recommended to manually update email constraints of existing users in the database after switching off support for duplicate email addresses.",
|
||||
"provideEmailTitle": "Provide your email address",
|
||||
"provideEmail": "To test connection, you should provide your email address first.",
|
||||
"verifyEmail": "Verify email",
|
||||
"verifyEmailHelpText": "Require user to verify their email address after initial login or after address changes are submitted.",
|
||||
"userInfoSettings": "User info settings",
|
||||
|
@ -123,8 +121,13 @@
|
|||
"enableSwitchSuccess": "{{switch}} changed successfully",
|
||||
"enableSwitchError": "Could not enable / disable due to {{error}}",
|
||||
"testConnection": "Test connection",
|
||||
"testConnectionHint": {
|
||||
"withEmail": "When testing the connection an e-mail will be sent to the current user ({{email}}).",
|
||||
"withoutEmail": "To test the connection you must first configure an e-mail address for the current user ({{userName}}).",
|
||||
"withoutEmailAction": "Configure e-mail address"
|
||||
},
|
||||
"testConnectionSuccess": "Success! SMTP connection successful. E-mail was sent!",
|
||||
"testConnectionError": "Error! Failed to send email.",
|
||||
"testConnectionError": "Error! {{error}}",
|
||||
"realmId": "Realm ID",
|
||||
"displayName": "Display name",
|
||||
"htmlDisplayName": "HTML Display name",
|
||||
|
|
|
@ -13,7 +13,7 @@ type AlertPanelProps = {
|
|||
|
||||
export function AlertPanel({ alerts, onCloseAlert }: AlertPanelProps) {
|
||||
return (
|
||||
<AlertGroup isToast>
|
||||
<AlertGroup data-testid="global-alerts" isToast>
|
||||
{alerts.map(({ id, variant, message, description }) => (
|
||||
<Alert
|
||||
key={id}
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
import {
|
||||
Button,
|
||||
ButtonVariant,
|
||||
Form,
|
||||
FormGroup,
|
||||
Modal,
|
||||
ModalVariant,
|
||||
TextContent,
|
||||
ValidatedOptions,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
import { emailRegexPattern } from "../util";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useWhoAmI } from "../context/whoami/WhoAmI";
|
||||
import { KeycloakTextInput } from "../components/keycloak-text-input/KeycloakTextInput";
|
||||
import type { EmailRegistrationCallback } from "./EmailTab";
|
||||
|
||||
type AddUserEmailModalProps = {
|
||||
callback: EmailRegistrationCallback;
|
||||
};
|
||||
|
||||
type AddUserEmailForm = {
|
||||
email: string;
|
||||
};
|
||||
|
||||
export const AddUserEmailModal = ({ callback }: AddUserEmailModalProps) => {
|
||||
const { t } = useTranslation("groups");
|
||||
const { adminClient } = useAdminClient();
|
||||
const { whoAmI } = useWhoAmI();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
watch,
|
||||
formState: { errors },
|
||||
} = useForm<AddUserEmailForm>({
|
||||
defaultValues: { email: "" },
|
||||
});
|
||||
|
||||
const watchEmailInput = watch("email", "");
|
||||
const cancel = () => callback(false);
|
||||
const proceed = () => callback(true);
|
||||
|
||||
const save = async (formData: AddUserEmailForm) => {
|
||||
await adminClient.users.update({ id: whoAmI.getUserId() }, formData);
|
||||
proceed();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
variant={ModalVariant.small}
|
||||
title={t("realm-settings:provideEmailTitle")}
|
||||
isOpen={true}
|
||||
onClose={cancel}
|
||||
actions={[
|
||||
<Button
|
||||
data-testid="modal-test-connection-button"
|
||||
key="confirm"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
form="email-form"
|
||||
isDisabled={!watchEmailInput}
|
||||
>
|
||||
{t("common:testConnection")}
|
||||
</Button>,
|
||||
<Button
|
||||
id="modal-cancel"
|
||||
data-testid="cancel"
|
||||
key="cancel"
|
||||
variant={ButtonVariant.link}
|
||||
onClick={cancel}
|
||||
>
|
||||
{t("common:cancel")}
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<TextContent className="kc-provide-email-text">
|
||||
{t("realm-settings:provideEmail")}
|
||||
</TextContent>
|
||||
<Form id="email-form" isHorizontal onSubmit={handleSubmit(save)}>
|
||||
<FormGroup
|
||||
className="kc-email-form-group"
|
||||
name="add-email-address"
|
||||
fieldId="email-id"
|
||||
helperTextInvalid={t("users:emailInvalid")}
|
||||
validated={
|
||||
errors.email ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
isRequired
|
||||
>
|
||||
<KeycloakTextInput
|
||||
data-testid="email-address-input"
|
||||
ref={register({ required: true, pattern: emailRegexPattern })}
|
||||
autoFocus
|
||||
type="text"
|
||||
id="add-email"
|
||||
name="email"
|
||||
validated={
|
||||
errors.email ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -1,5 +1,9 @@
|
|||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import {
|
||||
ActionGroup,
|
||||
ActionListItem,
|
||||
Alert,
|
||||
AlertActionLink,
|
||||
AlertVariant,
|
||||
Button,
|
||||
Checkbox,
|
||||
|
@ -7,29 +11,29 @@ import {
|
|||
PageSection,
|
||||
Switch,
|
||||
} from "@patternfly/react-core";
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import { useState } from "react";
|
||||
import { Controller, useForm, useWatch } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom-v5-compat";
|
||||
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { FormAccess } from "../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
import { FormPanel } from "../components/scroll-form/FormPanel";
|
||||
import { KeycloakTextInput } from "../components/keycloak-text-input/KeycloakTextInput";
|
||||
import { PasswordInput } from "../components/password-input/PasswordInput";
|
||||
import { FormPanel } from "../components/scroll-form/FormPanel";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { useWhoAmI } from "../context/whoami/WhoAmI";
|
||||
import { toUser } from "../user/routes/User";
|
||||
import { emailRegexPattern } from "../util";
|
||||
import { AddUserEmailModal } from "./AddUserEmailModal";
|
||||
import { PasswordInput } from "../components/password-input/PasswordInput";
|
||||
import { useCurrentUser } from "../utils/useCurrentUser";
|
||||
|
||||
import "./realm-settings-section.css";
|
||||
|
||||
type RealmSettingsEmailTabProps = {
|
||||
realm: RealmRepresentation;
|
||||
};
|
||||
|
||||
export type EmailRegistrationCallback = (registered: boolean) => void;
|
||||
|
||||
export const RealmSettingsEmailTab = ({
|
||||
realm: initialRealm,
|
||||
}: RealmSettingsEmailTabProps) => {
|
||||
|
@ -37,10 +41,9 @@ export const RealmSettingsEmailTab = ({
|
|||
const { adminClient } = useAdminClient();
|
||||
const { realm: realmName } = useRealm();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
const { whoAmI } = useWhoAmI();
|
||||
const currentUser = useCurrentUser();
|
||||
|
||||
const [realm, setRealm] = useState(initialRealm);
|
||||
const [callback, setCallback] = useState<EmailRegistrationCallback>();
|
||||
const {
|
||||
register,
|
||||
control,
|
||||
|
@ -63,12 +66,6 @@ export const RealmSettingsEmailTab = ({
|
|||
|
||||
const save = async (form: RealmRepresentation) => {
|
||||
try {
|
||||
const registered = await registerEmailIfNeeded();
|
||||
|
||||
if (!registered) {
|
||||
return;
|
||||
}
|
||||
|
||||
const savedRealm = { ...realm, ...form };
|
||||
|
||||
// For default value, back end is expecting null instead of empty string
|
||||
|
@ -102,12 +99,6 @@ export const RealmSettingsEmailTab = ({
|
|||
if (serverSettings.port === 0) serverSettings.port = null;
|
||||
|
||||
try {
|
||||
const registered = await registerEmailIfNeeded();
|
||||
|
||||
if (!registered) {
|
||||
return;
|
||||
}
|
||||
|
||||
await adminClient.realms.testSMTPConnection(
|
||||
{ realm: realm.realm! },
|
||||
serverSettings
|
||||
|
@ -118,276 +109,246 @@ export const RealmSettingsEmailTab = ({
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggers the flow to register the user's email if the user does not yet have one configured, if successful resolves true, otherwise false.
|
||||
*/
|
||||
const registerEmailIfNeeded = async () => {
|
||||
const user = await adminClient.users.findOne({ id: whoAmI.getUserId() });
|
||||
|
||||
// A user should always be found, throw if it is not.
|
||||
if (!user) {
|
||||
throw new Error("Unable to find user.");
|
||||
}
|
||||
|
||||
// User already has an e-mail associated with it, no need to register.
|
||||
if (user.email) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// User needs to register, show modal to do so.
|
||||
return new Promise<boolean>((resolve) => {
|
||||
const callback: EmailRegistrationCallback = (registered) => {
|
||||
setCallback(undefined);
|
||||
resolve(registered);
|
||||
};
|
||||
|
||||
setCallback(() => callback);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{callback && <AddUserEmailModal callback={callback} />}
|
||||
<PageSection variant="light">
|
||||
<FormPanel title={t("template")} className="kc-email-template">
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
role="manage-realm"
|
||||
className="pf-u-mt-lg"
|
||||
onSubmit={handleSubmit(save)}
|
||||
>
|
||||
<FormGroup
|
||||
label={t("from")}
|
||||
fieldId="kc-display-name"
|
||||
isRequired
|
||||
validated={errors.smtpServer?.from ? "error" : "default"}
|
||||
helperTextInvalid={t("users:emailInvalid")}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="email"
|
||||
id="kc-sender-email-address"
|
||||
data-testid="sender-email-address"
|
||||
name="smtpServer.from"
|
||||
ref={register({
|
||||
pattern: emailRegexPattern,
|
||||
required: true,
|
||||
})}
|
||||
placeholder="Sender email address"
|
||||
validated={errors.smtpServer?.from ? "error" : "default"}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("fromDisplayName")}
|
||||
fieldId="kc-from-display-name"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:fromDisplayName"
|
||||
fieldLabelId="realm-settings:authentication"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-from-display-name"
|
||||
data-testid="from-display-name"
|
||||
name="smtpServer.fromDisplayName"
|
||||
ref={register}
|
||||
placeholder="Display name for Sender email address"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("replyTo")}
|
||||
fieldId="kc-reply-to"
|
||||
validated={errors.smtpServer?.replyTo ? "error" : "default"}
|
||||
helperTextInvalid={t("users:emailInvalid")}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="email"
|
||||
id="kc-reply-to"
|
||||
name="smtpServer.replyTo"
|
||||
ref={register({
|
||||
pattern: emailRegexPattern,
|
||||
})}
|
||||
placeholder="Reply to email address"
|
||||
validated={errors.smtpServer?.replyTo ? "error" : "default"}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("replyToDisplayName")}
|
||||
fieldId="kc-reply-to-display-name"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:replyToDisplayName"
|
||||
fieldLabelId="realm-settings:replyToDisplayName"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-reply-to-display-name"
|
||||
name="smtpServer.replyToDisplayName"
|
||||
ref={register}
|
||||
placeholder='Display name for "reply to" email address'
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("envelopeFrom")}
|
||||
fieldId="kc-envelope-from"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:envelopeFrom"
|
||||
fieldLabelId="realm-settings:envelopeFrom"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-envelope-from"
|
||||
name="smtpServer.envelopeFrom"
|
||||
ref={register}
|
||||
placeholder="Sender envelope email address"
|
||||
/>
|
||||
</FormGroup>
|
||||
</FormAccess>
|
||||
</FormPanel>
|
||||
<FormPanel
|
||||
className="kc-email-connection"
|
||||
title={t("connectionAndAuthentication")}
|
||||
<PageSection variant="light">
|
||||
<FormPanel title={t("template")} className="kc-email-template">
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
role="manage-realm"
|
||||
className="pf-u-mt-lg"
|
||||
onSubmit={handleSubmit(save)}
|
||||
>
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
role="manage-realm"
|
||||
className="pf-u-mt-lg"
|
||||
onSubmit={handleSubmit(save)}
|
||||
<FormGroup
|
||||
label={t("from")}
|
||||
fieldId="kc-display-name"
|
||||
isRequired
|
||||
validated={errors.smtpServer?.from ? "error" : "default"}
|
||||
helperTextInvalid={t("users:emailInvalid")}
|
||||
>
|
||||
<FormGroup
|
||||
label={t("host")}
|
||||
fieldId="kc-host"
|
||||
isRequired
|
||||
<KeycloakTextInput
|
||||
type="email"
|
||||
id="kc-sender-email-address"
|
||||
data-testid="sender-email-address"
|
||||
name="smtpServer.from"
|
||||
ref={register({
|
||||
pattern: emailRegexPattern,
|
||||
required: true,
|
||||
})}
|
||||
placeholder="Sender email address"
|
||||
validated={errors.smtpServer?.from ? "error" : "default"}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("fromDisplayName")}
|
||||
fieldId="kc-from-display-name"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:fromDisplayName"
|
||||
fieldLabelId="realm-settings:authentication"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-from-display-name"
|
||||
data-testid="from-display-name"
|
||||
name="smtpServer.fromDisplayName"
|
||||
ref={register}
|
||||
placeholder="Display name for Sender email address"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("replyTo")}
|
||||
fieldId="kc-reply-to"
|
||||
validated={errors.smtpServer?.replyTo ? "error" : "default"}
|
||||
helperTextInvalid={t("users:emailInvalid")}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="email"
|
||||
id="kc-reply-to"
|
||||
name="smtpServer.replyTo"
|
||||
ref={register({
|
||||
pattern: emailRegexPattern,
|
||||
})}
|
||||
placeholder="Reply to email address"
|
||||
validated={errors.smtpServer?.replyTo ? "error" : "default"}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("replyToDisplayName")}
|
||||
fieldId="kc-reply-to-display-name"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:replyToDisplayName"
|
||||
fieldLabelId="realm-settings:replyToDisplayName"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-reply-to-display-name"
|
||||
name="smtpServer.replyToDisplayName"
|
||||
ref={register}
|
||||
placeholder='Display name for "reply to" email address'
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("envelopeFrom")}
|
||||
fieldId="kc-envelope-from"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:envelopeFrom"
|
||||
fieldLabelId="realm-settings:envelopeFrom"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-envelope-from"
|
||||
name="smtpServer.envelopeFrom"
|
||||
ref={register}
|
||||
placeholder="Sender envelope email address"
|
||||
/>
|
||||
</FormGroup>
|
||||
</FormAccess>
|
||||
</FormPanel>
|
||||
<FormPanel
|
||||
className="kc-email-connection"
|
||||
title={t("connectionAndAuthentication")}
|
||||
>
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
role="manage-realm"
|
||||
className="pf-u-mt-lg"
|
||||
onSubmit={handleSubmit(save)}
|
||||
>
|
||||
<FormGroup
|
||||
label={t("host")}
|
||||
fieldId="kc-host"
|
||||
isRequired
|
||||
validated={errors.smtpServer?.host ? "error" : "default"}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-host"
|
||||
name="smtpServer.host"
|
||||
ref={register({ required: true })}
|
||||
placeholder="SMTP host"
|
||||
validated={errors.smtpServer?.host ? "error" : "default"}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-host"
|
||||
name="smtpServer.host"
|
||||
ref={register({ required: true })}
|
||||
placeholder="SMTP host"
|
||||
validated={errors.smtpServer?.host ? "error" : "default"}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup label={t("port")} fieldId="kc-port">
|
||||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-port"
|
||||
name="smtpServer.port"
|
||||
ref={register}
|
||||
placeholder="SMTP port (defaults to 25)"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup label={t("encryption")} fieldId="kc-html-display-name">
|
||||
<Controller
|
||||
name="smtpServer.ssl"
|
||||
control={control}
|
||||
defaultValue="false"
|
||||
render={({ onChange, value }) => (
|
||||
<Checkbox
|
||||
id="kc-enable-ssl"
|
||||
data-testid="enable-ssl"
|
||||
label={t("enableSSL")}
|
||||
ref={register}
|
||||
isChecked={value === "true"}
|
||||
onChange={(value) => onChange("" + value)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="smtpServer.starttls"
|
||||
control={control}
|
||||
defaultValue="false"
|
||||
render={({ onChange, value }) => (
|
||||
<Checkbox
|
||||
id="kc-enable-start-tls"
|
||||
data-testid="enable-start-tls"
|
||||
label={t("enableStartTLS")}
|
||||
ref={register}
|
||||
isChecked={value === "true"}
|
||||
onChange={(value) => onChange("" + value)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
hasNoPaddingTop
|
||||
label={t("authentication")}
|
||||
fieldId="kc-authentication"
|
||||
>
|
||||
<Controller
|
||||
name="smtpServer.auth"
|
||||
control={control}
|
||||
defaultValue=""
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-authentication-switch"
|
||||
data-testid="email-authentication-switch"
|
||||
label={t("common:enabled")}
|
||||
labelOff={t("common:disabled")}
|
||||
isChecked={value === "true"}
|
||||
onChange={(value) => {
|
||||
onChange("" + value);
|
||||
}}
|
||||
aria-label={t("authentication")}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
{authenticationEnabled === "true" && (
|
||||
<>
|
||||
<FormGroup
|
||||
label={t("username")}
|
||||
fieldId="kc-username"
|
||||
isRequired
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup label={t("port")} fieldId="kc-port">
|
||||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-port"
|
||||
name="smtpServer.port"
|
||||
ref={register}
|
||||
placeholder="SMTP port (defaults to 25)"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup label={t("encryption")} fieldId="kc-html-display-name">
|
||||
<Controller
|
||||
name="smtpServer.ssl"
|
||||
control={control}
|
||||
defaultValue="false"
|
||||
render={({ onChange, value }) => (
|
||||
<Checkbox
|
||||
id="kc-enable-ssl"
|
||||
data-testid="enable-ssl"
|
||||
label={t("enableSSL")}
|
||||
ref={register}
|
||||
isChecked={value === "true"}
|
||||
onChange={(value) => onChange("" + value)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="smtpServer.starttls"
|
||||
control={control}
|
||||
defaultValue="false"
|
||||
render={({ onChange, value }) => (
|
||||
<Checkbox
|
||||
id="kc-enable-start-tls"
|
||||
data-testid="enable-start-tls"
|
||||
label={t("enableStartTLS")}
|
||||
ref={register}
|
||||
isChecked={value === "true"}
|
||||
onChange={(value) => onChange("" + value)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
hasNoPaddingTop
|
||||
label={t("authentication")}
|
||||
fieldId="kc-authentication"
|
||||
>
|
||||
<Controller
|
||||
name="smtpServer.auth"
|
||||
control={control}
|
||||
defaultValue=""
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-authentication-switch"
|
||||
data-testid="email-authentication-switch"
|
||||
label={t("common:enabled")}
|
||||
labelOff={t("common:disabled")}
|
||||
isChecked={value === "true"}
|
||||
onChange={(value) => {
|
||||
onChange("" + value);
|
||||
}}
|
||||
aria-label={t("authentication")}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
{authenticationEnabled === "true" && (
|
||||
<>
|
||||
<FormGroup
|
||||
label={t("username")}
|
||||
fieldId="kc-username"
|
||||
isRequired
|
||||
validated={errors.smtpServer?.user ? "error" : "default"}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-username"
|
||||
data-testid="username-input"
|
||||
name="smtpServer.user"
|
||||
ref={register({ required: true })}
|
||||
placeholder="Login username"
|
||||
validated={errors.smtpServer?.user ? "error" : "default"}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-username"
|
||||
data-testid="username-input"
|
||||
name="smtpServer.user"
|
||||
ref={register({ required: true })}
|
||||
placeholder="Login username"
|
||||
validated={errors.smtpServer?.user ? "error" : "default"}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("password")}
|
||||
fieldId="kc-username"
|
||||
isRequired
|
||||
validated={errors.smtpServer?.password ? "error" : "default"}
|
||||
helperTextInvalid={t("common:required")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:password"
|
||||
fieldLabelId="realm-settings:password"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("password")}
|
||||
fieldId="kc-username"
|
||||
isRequired
|
||||
}
|
||||
>
|
||||
<PasswordInput
|
||||
id="kc-password"
|
||||
data-testid="password-input"
|
||||
name="smtpServer.password"
|
||||
aria-label={t("password")}
|
||||
validated={errors.smtpServer?.password ? "error" : "default"}
|
||||
helperTextInvalid={t("common:required")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:password"
|
||||
fieldLabelId="realm-settings:password"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<PasswordInput
|
||||
id="kc-password"
|
||||
data-testid="password-input"
|
||||
name="smtpServer.password"
|
||||
aria-label={t("password")}
|
||||
validated={
|
||||
errors.smtpServer?.password ? "error" : "default"
|
||||
}
|
||||
ref={register({ required: true })}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
)}
|
||||
ref={register({ required: true })}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
)}
|
||||
|
||||
<ActionGroup>
|
||||
<ActionGroup>
|
||||
<ActionListItem>
|
||||
<Button
|
||||
variant="primary"
|
||||
type="submit"
|
||||
|
@ -395,16 +356,22 @@ export const RealmSettingsEmailTab = ({
|
|||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
</ActionListItem>
|
||||
<ActionListItem>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => testConnection()}
|
||||
data-testid="test-connection-button"
|
||||
isDisabled={
|
||||
!(emailRegexPattern.test(watchFromValue) && watchHostValue)
|
||||
!(emailRegexPattern.test(watchFromValue) && watchHostValue) ||
|
||||
!currentUser?.email
|
||||
}
|
||||
aria-describedby="descriptionTestConnection"
|
||||
>
|
||||
{t("common:testConnection")}
|
||||
</Button>
|
||||
</ActionListItem>
|
||||
<ActionListItem>
|
||||
<Button
|
||||
variant="link"
|
||||
onClick={reset}
|
||||
|
@ -412,10 +379,47 @@ export const RealmSettingsEmailTab = ({
|
|||
>
|
||||
{t("common:revert")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
||||
</FormPanel>
|
||||
</PageSection>
|
||||
</>
|
||||
</ActionListItem>
|
||||
</ActionGroup>
|
||||
{currentUser && (
|
||||
<FormGroup id="descriptionTestConnection">
|
||||
{currentUser.email ? (
|
||||
<Alert
|
||||
variant="info"
|
||||
isInline
|
||||
title={t("testConnectionHint.withEmail", {
|
||||
email: currentUser.email,
|
||||
})}
|
||||
/>
|
||||
) : (
|
||||
<Alert
|
||||
variant="warning"
|
||||
isInline
|
||||
title={t("testConnectionHint.withoutEmail", {
|
||||
userName: currentUser.username,
|
||||
})}
|
||||
actionLinks={
|
||||
<AlertActionLink
|
||||
component={(props) => (
|
||||
<Link
|
||||
{...props}
|
||||
to={toUser({
|
||||
realm: realmName,
|
||||
id: currentUser.id!,
|
||||
tab: "settings",
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
{t("testConnectionHint.withoutEmailAction")}
|
||||
</AlertActionLink>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</FormGroup>
|
||||
)}
|
||||
</FormAccess>
|
||||
</FormPanel>
|
||||
</PageSection>
|
||||
);
|
||||
};
|
||||
|
|
18
apps/admin-ui/src/utils/useCurrentUser.ts
Normal file
18
apps/admin-ui/src/utils/useCurrentUser.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
|
||||
import { useState } from "react";
|
||||
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
||||
import { useWhoAmI } from "../context/whoami/WhoAmI";
|
||||
|
||||
export function useCurrentUser() {
|
||||
const { whoAmI } = useWhoAmI();
|
||||
const { adminClient } = useAdminClient();
|
||||
const [currentUser, setCurrentUser] = useState<UserRepresentation>();
|
||||
|
||||
const userId = whoAmI.getUserId();
|
||||
|
||||
useFetch(() => adminClient.users.findOne({ id: userId }), setCurrentUser, [
|
||||
userId,
|
||||
]);
|
||||
|
||||
return currentUser;
|
||||
}
|
Loading…
Reference in a new issue