diff --git a/forms/src/main/java/org/keycloak/forms/ErrorBean.java b/forms/src/main/java/org/keycloak/forms/MessageBean.java similarity index 78% rename from forms/src/main/java/org/keycloak/forms/ErrorBean.java rename to forms/src/main/java/org/keycloak/forms/MessageBean.java index d6c18b6a61..c1b16a457c 100644 --- a/forms/src/main/java/org/keycloak/forms/ErrorBean.java +++ b/forms/src/main/java/org/keycloak/forms/MessageBean.java @@ -26,18 +26,18 @@ import org.keycloak.services.resources.flows.FormFlows; /** * @author Stian Thorgersen */ -public class ErrorBean { +public class MessageBean { private String summary; - private FormFlows.ErrorType type; + private FormFlows.MessageType type; // Message is considered ERROR by default - public ErrorBean(String summary) { - this(summary, FormFlows.ErrorType.ERROR); + public MessageBean(String summary) { + this(summary, FormFlows.MessageType.ERROR); } - public ErrorBean(String summary, FormFlows.ErrorType type) { + public MessageBean(String summary, FormFlows.MessageType type) { this.summary = summary; this.type = type; } @@ -47,15 +47,15 @@ public class ErrorBean { } public boolean isSuccess(){ - return FormFlows.ErrorType.SUCCESS.equals(this.type); + return FormFlows.MessageType.SUCCESS.equals(this.type); } public boolean isWarning(){ - return FormFlows.ErrorType.WARNING.equals(this.type); + return FormFlows.MessageType.WARNING.equals(this.type); } public boolean isError(){ - return FormFlows.ErrorType.ERROR.equals(this.type); + return FormFlows.MessageType.ERROR.equals(this.type); } } \ No newline at end of file diff --git a/forms/src/main/java/org/keycloak/service/FormServiceImpl.java b/forms/src/main/java/org/keycloak/service/FormServiceImpl.java index 9489448ebe..64624e471e 100644 --- a/forms/src/main/java/org/keycloak/service/FormServiceImpl.java +++ b/forms/src/main/java/org/keycloak/service/FormServiceImpl.java @@ -32,7 +32,7 @@ import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import org.jboss.resteasy.logging.Logger; -import org.keycloak.forms.ErrorBean; +import org.keycloak.forms.MessageBean; import org.keycloak.forms.LoginBean; import org.keycloak.forms.OAuthGrantBean; import org.keycloak.forms.RealmBean; @@ -69,8 +69,7 @@ public class FormServiceImpl implements FormService { commandMap.put(Pages.TOTP, new CommandTotp()); commandMap.put(Pages.LOGIN_CONFIG_TOTP, new CommandTotp()); commandMap.put(Pages.LOGIN_TOTP, new CommandLoginTotp()); - commandMap.put(Pages.LOGIN_VERIFY_EMAIL, new CommandLoginTotp()); - commandMap.put(Pages.ERROR, new CommandError()); + commandMap.put(Pages.LOGIN_VERIFY_EMAIL, new CommandVerifyEmail()); commandMap.put(Pages.OAUTH_GRANT, new CommandOAuthGrant()); } @@ -82,8 +81,8 @@ public class FormServiceImpl implements FormService { Map attributes = new HashMap(); - if (dataBean.getError() != null){ - attributes.put("message", new ErrorBean(dataBean.getError(), dataBean.getErrorType())); + if (dataBean.getMessage() != null){ + attributes.put("message", new MessageBean(dataBean.getMessage(), dataBean.getMessageType())); } RealmBean realm = new RealmBean(dataBean.getRealm()); @@ -161,9 +160,6 @@ public class FormServiceImpl implements FormService { private class CommandLoginTotp implements Command { public void exec(Map attributes, FormServiceDataBean dataBean) { - if (dataBean.getError() != null){ - attributes.put("error", new ErrorBean(dataBean.getError())); - } RealmBean realm = new RealmBean(dataBean.getRealm()); @@ -206,10 +202,6 @@ public class FormServiceImpl implements FormService { private class CommandLogin implements Command { public void exec(Map attributes, FormServiceDataBean dataBean) { - if (dataBean.getError() != null){ - attributes.put("error", new ErrorBean(dataBean.getError())); - } - RealmBean realm = new RealmBean(dataBean.getRealm()); attributes.put("realm", realm); @@ -230,9 +222,6 @@ public class FormServiceImpl implements FormService { private class CommandRegister implements Command { public void exec(Map attributes, FormServiceDataBean dataBean) { - if (dataBean.getError() != null){ - attributes.put("error", new ErrorBean(dataBean.getError())); - } RealmBean realm = new RealmBean(dataBean.getRealm()); @@ -252,14 +241,6 @@ public class FormServiceImpl implements FormService { } } - private class CommandError implements Command { - public void exec(Map attributes, FormServiceDataBean dataBean) { - if (dataBean.getError() != null){ - attributes.put("error", new ErrorBean(dataBean.getError())); - } - } - } - private class CommandOAuthGrant implements Command { public void exec(Map attributes, FormServiceDataBean dataBean) { @@ -274,6 +255,20 @@ public class FormServiceImpl implements FormService { } } + private class CommandVerifyEmail implements Command { + public void exec(Map attributes, FormServiceDataBean dataBean) { + + RealmBean realm = new RealmBean(dataBean.getRealm()); + + attributes.put("realm", realm); + + UrlBean url = new UrlBean(realm, dataBean.getBaseURI()); + url.setSocialRegistration(dataBean.getSocialRegistration()); + + attributes.put("url", url); + } + } + private interface Command { public void exec(Map attributes, FormServiceDataBean dataBean); } diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/css/login-register.css b/forms/src/main/resources/META-INF/resources/forms/theme/default/css/login-register.css index 8eacd72561..eca69a22c3 100644 --- a/forms/src/main/resources/META-INF/resources/forms/theme/default/css/login-register.css +++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/css/login-register.css @@ -291,9 +291,6 @@ a.zocial:before { .rcue-login-register.reset .background-area .section.app-form { width: 43.2em; } -.rcue-login-register.reset .feedback { - left: 35.7em; -} .rcue-login-register.oauth .form-actions { margin-bottom: 0; diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/error.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/error.ftl index 659fce1e1a..fd3fc1ebee 100755 --- a/forms/src/main/resources/META-INF/resources/forms/theme/default/error.ftl +++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/error.ftl @@ -12,7 +12,7 @@ <#elseif section = "form">

Something happened and we could not process your request.

-

${error.summary}

+

${message.summary}

<#elseif section = "info" > diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/login-config-totp.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/login-config-totp.ftl index 2b1c1c5c9a..97ff4adf47 100755 --- a/forms/src/main/resources/META-INF/resources/forms/theme/default/login-config-totp.ftl +++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/login-config-totp.ftl @@ -8,11 +8,6 @@ Google Authenticator Setup - <#elseif section = "feedback"> - - <#elseif section = "form">
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/login-reset-password.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/login-reset-password.ftl index ad80199ed5..af308ac13c 100755 --- a/forms/src/main/resources/META-INF/resources/forms/theme/default/login-reset-password.ftl +++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/login-reset-password.ftl @@ -11,15 +11,6 @@ <#elseif section = "form">
- <#if message?has_content> - <#if message.success> - - - <#if message.error> - - - -

${rb.getString('emailInstruction')}

diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/login-verify-email.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/login-verify-email.ftl index cff75f1086..0832666004 100755 --- a/forms/src/main/resources/META-INF/resources/forms/theme/default/login-verify-email.ftl +++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/login-verify-email.ftl @@ -8,11 +8,6 @@ Email verification - <#elseif section = "feedback"> - - <#elseif section = "form">
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login-action.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login-action.ftl index c2920cf57f..303aeebd68 100644 --- a/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login-action.ftl +++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login-action.ftl @@ -17,7 +17,11 @@ <#if (template.themeConfig.logo)?has_content>

@@ -33,18 +37,26 @@
+ <#if !isErrorPage && message?has_content> + <#if message.error> + + <#elseif message.success> + + + +

Application login area

<#nested "form">
- <#if !isErrorPage && error?has_content> - - -

Info area

<#nested "info"> diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login.ftl index de023e1bfb..d64a3c694e 100644 --- a/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login.ftl +++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login.ftl @@ -31,10 +31,10 @@

Application login area

- <#if error?has_content> + <#if message?has_content && message.error> diff --git a/forms/src/main/resources/org/keycloak/forms/messages.properties b/forms/src/main/resources/org/keycloak/forms/messages.properties index 03943dc0e1..8fb4f12000 100644 --- a/forms/src/main/resources/org/keycloak/forms/messages.properties +++ b/forms/src/main/resources/org/keycloak/forms/messages.properties @@ -31,6 +31,7 @@ missingLastName=Please specify last name missingEmail=Please specify email missingUsername=Please specify username missingPassword=Please specify password +notMatchPassword=Passwords don't match missingTotp=Please specify authenticator code invalidPasswordExisting=Invalid existing password @@ -43,6 +44,12 @@ successTotpRemoved=Google authenticator removed. usernameExists=Username already exists error=A system error has occured, contact admin +actionWarningHeader=Your account is not enabled. +actionTotpWarning=You need to set up the Google Authenticator to activate your account. +actionProfileWarning=You need to update your user profile to activate your account. +actionPasswordWarning=You need to change your password to activate your account. +actionEmailWarning=You need to verify your email address to activate your account. +actionFollow=Please follow the steps below. successHeader=Success! errorHeader=Error! diff --git a/services/src/main/java/org/keycloak/services/FormService.java b/services/src/main/java/org/keycloak/services/FormService.java index 6e5813855b..70e4c0fc03 100755 --- a/services/src/main/java/org/keycloak/services/FormService.java +++ b/services/src/main/java/org/keycloak/services/FormService.java @@ -44,9 +44,9 @@ public interface FormService { private RealmModel realm; private UserModel userModel; - private String error; + private String message; - private FormFlows.ErrorType errorType; + private FormFlows.MessageType messageType; private MultivaluedMap formData; private URI baseURI; @@ -81,11 +81,11 @@ public interface FormService { private String contextPath; - public FormServiceDataBean(RealmModel realm, UserModel userModel, MultivaluedMap formData, String error){ + public FormServiceDataBean(RealmModel realm, UserModel userModel, MultivaluedMap formData, String message){ this.realm = realm; this.userModel = userModel; this.formData = formData; - this.error = error; + this.message = message; } public URI getBaseURI() { @@ -96,12 +96,12 @@ public interface FormService { this.baseURI = baseURI; } - public String getError() { - return error; + public String getMessage() { + return message; } - public void setError(String error) { - this.error = error; + public void setMessage(String message) { + this.message = message; } public MultivaluedMap getFormData() { @@ -128,12 +128,12 @@ public interface FormService { this.userModel = userModel; } - public FormFlows.ErrorType getErrorType() { - return errorType; + public FormFlows.MessageType getMessageType() { + return messageType; } - public void setErrorType(FormFlows.ErrorType errorType) { - this.errorType = errorType; + public void setMessageType(FormFlows.MessageType messageType) { + this.messageType = messageType; } /* OAuth Part */ diff --git a/services/src/main/java/org/keycloak/services/messages/Messages.java b/services/src/main/java/org/keycloak/services/messages/Messages.java index 3b7a760d0e..2c659fbd57 100644 --- a/services/src/main/java/org/keycloak/services/messages/Messages.java +++ b/services/src/main/java/org/keycloak/services/messages/Messages.java @@ -44,6 +44,8 @@ public class Messages { public static final String MISSING_PASSWORD = "missingPassword"; + public static final String NOTMATCH_PASSWORD = "notMatchPassword"; + public static final String MISSING_USERNAME = "missingUsername"; public static final String MISSING_TOTP = "missingTotp"; @@ -52,6 +54,14 @@ public class Messages { public static final String USERNAME_EXISTS = "usernameExists"; + public static final String ACTION_WARN_TOTP = "actionTotpWarning"; + + public static final String ACTION_WARN_PROFILE = "actionProfileWarning"; + + public static final String ACTION_WARN_PASSWD = "actionPasswordWarning"; + + public static final String ACTION_WARN_EMAIL = "actionEmailWarning"; + public static final String ERROR = "error"; } diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java index 7f54e5232a..7205d6f73c 100755 --- a/services/src/main/java/org/keycloak/services/resources/AccountService.java +++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java @@ -115,7 +115,7 @@ public class AccountService { public Response processTotpRemove() { UserModel user = getUserFromAuthManager(); user.setTotp(false); - return Flows.forms(realm, request, uriInfo).setError("successTotpRemoved").setErrorType(FormFlows.ErrorType.SUCCESS) + return Flows.forms(realm, request, uriInfo).setError("successTotpRemoved").setErrorType(FormFlows.MessageType.SUCCESS) .setUser(user).forwardToTotp(); } @@ -152,7 +152,7 @@ public class AccountService { user.setTotp(true); - return Flows.forms(realm, request, uriInfo).setError("successTotp").setErrorType(FormFlows.ErrorType.SUCCESS) + return Flows.forms(realm, request, uriInfo).setError("successTotp").setErrorType(FormFlows.MessageType.SUCCESS) .setUser(user).forwardToTotp(); } diff --git a/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java b/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java index 1517b799c1..67a241e4e6 100755 --- a/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java +++ b/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java @@ -88,6 +88,12 @@ public class RequiredActionsService { } UserModel user = getUser(accessCode); + + String error = Validation.validateUpdateProfileForm(formData); + if (error != null) { + return Flows.forms(realm, request, uriInfo).setError(error).forwardToAction(RequiredAction.UPDATE_PROFILE); + } + user.setFirstName(formData.getFirst("firstName")); user.setLastName(formData.getFirst("lastName")); user.setEmail(formData.getFirst("email")); @@ -146,15 +152,14 @@ public class RequiredActionsService { UserModel user = getUser(accessCode); - String password = formData.getFirst("password"); String passwordNew = formData.getFirst("password-new"); String passwordConfirm = formData.getFirst("password-confirm"); FormFlows forms = Flows.forms(realm, request, uriInfo).setUser(user); if (Validation.isEmpty(passwordNew)) { - forms.setError(Messages.MISSING_PASSWORD).forwardToAction(RequiredAction.UPDATE_PASSWORD); + return forms.setError(Messages.MISSING_PASSWORD).forwardToAction(RequiredAction.UPDATE_PASSWORD); } else if (!passwordNew.equals(passwordConfirm)) { - forms.setError(Messages.MISSING_PASSWORD).forwardToAction(RequiredAction.UPDATE_PASSWORD); + return forms.setError(Messages.NOTMATCH_PASSWORD).forwardToAction(RequiredAction.UPDATE_PASSWORD); } UserCredentialModel credentials = new UserCredentialModel(); @@ -257,7 +262,7 @@ public class RequiredActionsService { new EmailSender().sendPasswordReset(user, realm, accessCode, uriInfo); - return Flows.forms(realm, request, uriInfo).setError("emailSent").setErrorType(FormFlows.ErrorType.SUCCESS) + return Flows.forms(realm, request, uriInfo).setError("emailSent").setErrorType(FormFlows.MessageType.SUCCESS) .forwardToPasswordReset(); } diff --git a/services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java b/services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java index c4fe4a6d25..2aebb4e84b 100755 --- a/services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java +++ b/services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java @@ -34,6 +34,7 @@ import org.keycloak.services.managers.AccessCodeEntry; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserModel.RequiredAction; +import org.keycloak.services.messages.Messages; import org.picketlink.idm.model.sample.Realm; import javax.imageio.spi.ServiceRegistry; @@ -58,8 +59,8 @@ public class FormFlows { // TODO refactor/rename "error" to "message" everywhere where it makes sense private String error; - public static enum ErrorType {SUCCESS, WARNING, ERROR}; - private ErrorType errorType; + public static enum MessageType {SUCCESS, WARNING, ERROR}; + private MessageType messageType = MessageType.ERROR; private MultivaluedMap formData; @@ -79,16 +80,17 @@ public class FormFlows { } public Response forwardToAction(RequiredAction action) { + switch (action) { case CONFIGURE_TOTP: - return forwardToForm(Pages.LOGIN_CONFIG_TOTP); + return forwardToActionForm(Pages.LOGIN_CONFIG_TOTP, Messages.ACTION_WARN_TOTP); case UPDATE_PROFILE: - return forwardToForm(Pages.LOGIN_UPDATE_PROFILE); + return forwardToActionForm(Pages.LOGIN_UPDATE_PROFILE, Messages.ACTION_WARN_PROFILE); case UPDATE_PASSWORD: - return forwardToForm(Pages.LOGIN_UPDATE_PASSWORD); + return forwardToActionForm(Pages.LOGIN_UPDATE_PASSWORD, Messages.ACTION_WARN_PASSWD); case VERIFY_EMAIL: new EmailSender().sendEmailVerification(userModel, realm, accessCode, uriInfo); - return forwardToForm(Pages.LOGIN_VERIFY_EMAIL); + return forwardToActionForm(Pages.LOGIN_VERIFY_EMAIL, Messages.ACTION_WARN_EMAIL); default: return Response.serverError().build(); } @@ -103,7 +105,6 @@ public class FormFlows { } private Response forwardToForm(String template, FormService.FormServiceDataBean formDataBean) { - formDataBean.setErrorType(errorType == null ? ErrorType.ERROR : errorType); // Getting URI needed by form processing service ResteasyUriInfo uriInfo = request.getUri(); @@ -143,8 +144,21 @@ public class FormFlows { private Response forwardToForm(String template) { FormService.FormServiceDataBean formDataBean = new FormService.FormServiceDataBean(realm, userModel, formData, error); - return forwardToForm(template, formDataBean); + formDataBean.setMessageType(messageType); + return forwardToForm(template, formDataBean); + } + + private Response forwardToActionForm(String template, String warningSummary) { + + // If no other message is set, notify user about required action in the warning window + // so it's clear that this is a req. action form not a login form + if (error == null){ + messageType = MessageType.WARNING; + error = warningSummary; + } + + return forwardToForm(template); } public Response forwardToLogin() { @@ -202,8 +216,8 @@ public class FormFlows { return this; } - public FormFlows setErrorType(ErrorType errorType) { - this.errorType = errorType; + public FormFlows setErrorType(MessageType errorType) { + this.messageType = errorType; return this; } diff --git a/services/src/main/java/org/keycloak/services/validation/Validation.java b/services/src/main/java/org/keycloak/services/validation/Validation.java index 5a71f0d9f7..c652849f99 100755 --- a/services/src/main/java/org/keycloak/services/validation/Validation.java +++ b/services/src/main/java/org/keycloak/services/validation/Validation.java @@ -38,6 +38,22 @@ public class Validation { return null; } + public static String validateUpdateProfileForm(MultivaluedMap formData) { + if (isEmpty(formData.getFirst("firstName"))) { + return Messages.MISSING_FIRST_NAME; + } + + if (isEmpty(formData.getFirst("lastName"))) { + return Messages.MISSING_LAST_NAME; + } + + if (isEmpty(formData.getFirst("email"))) { + return Messages.MISSING_EMAIL; + } + + return null; + } + public static boolean isEmpty(String s) { return s == null || s.length() == 0; } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileTest.java index 08a2bfa3e7..c567e99104 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileTest.java @@ -44,8 +44,8 @@ import org.openqa.selenium.WebDriver; */ public class RequiredActionUpdateProfileTest { - @ClassRule - public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() { + @Rule + public KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { @@ -83,4 +83,50 @@ public class RequiredActionUpdateProfileTest { Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType()); } + @Test + public void updateProfileMissingFirstName() { + loginPage.open(); + + loginPage.login("test-user@localhost", "password"); + + updateProfilePage.assertCurrent(); + + updateProfilePage.update("", "New last", "new@email.com"); + + updateProfilePage.assertCurrent(); + + Assert.assertEquals("Please specify first name", updateProfilePage.getError()); + } + + @Test + public void updateProfileMissingLastName() { + loginPage.open(); + + loginPage.login("test-user@localhost", "password"); + + updateProfilePage.assertCurrent(); + + updateProfilePage.update("New first", "", "new@email.com"); + + updateProfilePage.assertCurrent(); + + Assert.assertEquals("Please specify last name", updateProfilePage.getError()); + } + + @Test + public void updateProfileMissingEmail() { + loginPage.open(); + + loginPage.login("test-user@localhost", "password"); + + updateProfilePage.assertCurrent(); + + updateProfilePage.update("New first", "New last", ""); + + updateProfilePage.assertCurrent(); + + Assert.assertEquals("Please specify email", updateProfilePage.getError()); + } + + } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java index 9b5ca0f1b9..396f3d9411 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java @@ -123,7 +123,7 @@ public class ResetPasswordTest { resetPasswordPage.assertCurrent(); Assert.assertNotEquals("Success!", resetPasswordPage.getMessage()); - Assert.assertEquals("Error!", resetPasswordPage.getMessage()); + Assert.assertEquals("Invalid username or email.", resetPasswordPage.getMessage()); } @Test @@ -138,7 +138,7 @@ public class ResetPasswordTest { resetPasswordPage.assertCurrent(); Assert.assertNotEquals("Success!", resetPasswordPage.getMessage()); - Assert.assertEquals("Error!", resetPasswordPage.getMessage()); + Assert.assertEquals("Invalid username or email.", resetPasswordPage.getMessage()); } }