KEYCLOAK-112 - fixing various forms UI related issues

This commit is contained in:
vrockai 2013-10-21 18:23:53 +02:00
parent 115c0bdeca
commit f7d6c41304
14 changed files with 86 additions and 301 deletions

View file

@ -15,7 +15,7 @@
</div>
<div class="form-group">
<label for="email">${rb.getString('email')}</label><span class="required">*</span>
<input type="email" id="email" name="email" autofocus value="${user.email!''}"/>
<input type="text" id="email" name="email" autofocus value="${user.email!''}"/>
</div>
<div class="form-group">
<label for="lastName">${rb.getString('lastName')}</label><span class="required">*</span>
@ -27,7 +27,7 @@
</div>
</fieldset>
<div class="form-actions">
<a href="#">« Back to my application</a>
<#--a href="#">« Back to my application</a-->
<button type="submit" class="primary">Save</button>
<button type="submit">Cancel</button>
</div>

View file

@ -185,43 +185,6 @@ table a:hover {
font-weight: normal;
margin-left: 1em;
}
.tooltip-box {
position: absolute;
font-size: 1em;
background-image: url("img/tooltip-box-arrow-right-up.svg");
background-position: right top;
background-repeat: no-repeat;
padding-top: 1em;
right: 0;
top: 1.5em;
font-size: 0.90909090909091em;
}
.tooltip-box fieldset {
width: 30.8em;
padding-left: 1.5em;
padding-right: 1.5em;
padding-top: .5em;
background-color: #fff;
border: 1px solid #b6b6b6;
border-top: none;
border-radius: 0 2px 2px 2px;
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.15);
}
.tooltip-box fieldset legend {
display: none;
}
.tooltip-box fieldset label {
width: 6em;
}
.tooltip-box fieldset .form-actions {
margin: 0;
padding: 1em 1.5em 1em 0;
background-color: #f8f8f8;
display: block;
float: none;
margin-right: -1.5em;
margin-left: -1.5em;
}
td.token-cell button {
margin-top: -1px;
}

View file

@ -307,9 +307,7 @@ button[class^="icon-"] {
padding: 0;
line-height: 1em;
}
button[class^="icon-"]:hover {
background-image: url(img/sprites.png);
}
legend {
font-size: 1em;
border-width: 1px 0 0 0;
@ -328,14 +326,7 @@ legend .text {
font-weight: bold;
font-size: 1.25em;
}
legend .icon-info {
background-image: url(img/sprites-gray.png);
margin-left: 1em;
vertical-align: baseline;
}
legend .icon-info:hover {
background-image: url(img/sprites.png);
}
.form-group {
display: block;
margin-bottom: 1em;
@ -377,7 +368,7 @@ legend + table {
margin-top: 1em;
}
.code {
font-family: Courier, monospace;
font-family: Courier, monospace;
}
.onoffswitch {
-moz-user-select: none;
@ -460,20 +451,6 @@ input[type="email"].tiny {
min-width: 40px;
width: 40px;
}
.select-rcue,
.select2-container .select2-choice {
height: 26px;
border: 1px #b6b6b6 solid;
border-radius: 2px;
box-shadow: inset 0px 2px 2px rgba(0, 0, 0, 0.1);
color: #333;
background: #ffffff url(img/select-arrow.png) no-repeat right center;
overflow: hidden;
min-width: 75px;
padding: 0 0.9em 0 0;
display: inline-block;
font-family: "Open Sans", sans-serif;
}
.select-rcue:hover {
border-color: #62afdb;
}
@ -510,93 +487,7 @@ input[type="email"].tiny {
.select-rcue option:hover {
background-color: #d5ecf9;
}
.select2-container {
float: left;
margin-top: 0.3em;
margin-bottom: 0.3em;
}
.select2-container .select2-choice > .select2-chosen {
line-height: 2.1em;
padding-left: 0.90909090909091em;
margin-right: 0;
font-size: 1.1em;
padding-right: 2.36363636363636em;
padding-right: 26px;
}
.select2-container .select2-choice .select2-arrow {
display: none;
}
.select2-dropdown-open {
background-color: #fff;
}
.select2-dropdown-open .select2-choice,
.select2-dropdown-open .select2-choices {
border-bottom: none;
border-radius: 2px 2px 0 0;
background-image: url(img/chosen-arrow-down.png);
background-color: transparent;
background-repeat: no-repeat;
background-position: right top;
box-shadow: none;
}
.select2-dropdown-open .select2-choice,
.select2-dropdown-open.select2-drop-above .select2-choice,
.select2-dropdown-open .select2-choices,
.select2-dropdown-open.select2-drop-above .select2-choices {
border-color: #62AFDB;
}
.select2-search input {
min-width: 0;
}
.select2-drop-active {
border-radius: 0 0 2px 2px;
margin-top: -1px;
padding-top: 4px;
}
.select2-container.select2-drop-above .select2-choice {
border-radius: 0 0 2px 2px;
background-image: url(img/chosen-arrow-up.png);
background-repeat: no-repeat;
background-position: right 0;
box-shadow: none;
}
.select2-drop.select2-drop-above {
border-radius: 2px 2px 0 0;
padding-top: 0;
margin-top: 2px;
}
.select2-drop.select2-drop-above.select2-drop-active,
.select2-drop-active {
border-color: #62AFDB;
}
.select2-results {
padding-left: 0;
margin-right: 0;
}
.select2-results li {
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
}
.select2-results .select2-result-label,
.select2-results .select2-no-results,
.select2-results .select2-searching,
.select2-results .select2-selection-limit {
font-size: 1.1em;
padding-left: 1.09090909090909em;
}
.select2-results .select2-no-results,
.select2-results .select2-searching,
.select2-results .select2-selection-limit {
color: #838383;
padding-top: 3px;
padding-bottom: 4px;
}
.select2-results .select2-highlighted {
background-color: #d5ecf9;
border-top: 1px solid #a7d7f1;
border-bottom: 1px solid #a7d7f1;
color: #4d5258;
}
.input-group input + .select-rcue {
border-radius: 0 2px 2px 0;
border-left: 0;
@ -605,93 +496,7 @@ input[type="email"].tiny {
.input-select .input-group input {
float: left;
}
.tokenfield.form-control {
width: 40em;
float: left;
min-height: 2.6em;
border: 1px #b6b6b6 solid;
border-radius: 2px;
box-shadow: inset 0px 2px 2px rgba(0, 0, 0, 0.1);
padding: 0 0.7em;
margin-bottom: 0;
font-size: 1em;
height: auto;
outline: 0 none;
}
.tokenfield.form-control .token {
display: inline-block;
background-color: #d4ecf8;
border: 1px solid #a3d7f0;
border-radius: 1px;
padding: 0 0.3em 0 0.7em;
margin-right: 0.7em;
margin-top: 0.3em;
margin-bottom: 0.3em;
outline: 0 none;
}
.tokenfield.form-control .token span {
float: left;
font-size: 1.1em;
line-height: 1.45454545454545em;
}
.tokenfield.form-control .token .close {
text-indent: -99999em;
width: 1.6em;
height: 1.6em;
line-height: 1.6em;
background: url(img/btn-close-blue.png) no-repeat center center;
margin-left: 0.3em;
padding: 0;
border: none;
font-size: 1em;
opacity: 1;
}
.tokenfield.form-control input {
padding: 0;
border: none;
font-size: 1.1em;
line-height: 1.63636363636364em;
height: 1.63636363636364em;
margin: 0.272727272727273em 0;
box-shadow: none;
outline: 0 none;
float: left;
}
.tokenfield.form-control:hover {
border-color: #62afdb;
}
.tokenfield.form-control:focus {
border-color: #62afdb;
box-shadow: #62afdb 0 0 5px;
}
.token {
float: left;
background-color: #d4ecf8;
border: 1px solid #a3d7f0;
border-radius: 1px;
padding: 0 0.3em 0 0.7em;
margin-right: 0.7em;
margin-top: 0.3em;
margin-bottom: 0.3em;
outline: 0 none;
}
.token span {
float: left;
font-size: 1.1em;
line-height: 1.45454545454545em;
}
.token .close {
text-indent: -9999999em;
width: 1.6em;
height: 1.6em;
line-height: 1.6em;
background: url(img/btn-close-blue.png) no-repeat center center;
margin-left: 0.3em;
padding: 0;
border: none;
font-size: 1em;
opacity: 1;
}
.form-actions {
float: right;
margin-top: 3em;

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

View file

@ -3,9 +3,9 @@ body {
min-height: 60em;
min-width: 120em;
}
.rcue-login-register {
background-color: #1D2226;
background-image: url("img/login-screen-background.jpg");
background-position: top left;
background-size: auto;
background-repeat: no-repeat;
@ -17,6 +17,7 @@ body {
/* Info area */
}
.rcue-login-register h1 a {
position: absolute;
top: 5em;
@ -61,12 +62,12 @@ body {
padding-right: 4.5em;
}
.rcue-login-register .form-area {
background-image: url(img/login-register-separator.svg);
background-image: url(img/login-register-separator.png);
background-repeat: no-repeat;
background-position: 40.2em center;
}
.rcue-login-register .form-area.social {
background-image: url(img/login-register-social-separators.svg);
background-image: url(img/login-register-social-separators.png);
background-position: 39.6em center;
}
.rcue-login-register .section > p {
@ -267,10 +268,6 @@ a.zocial:before {
.rcue-login-register.register form > div.aside-btn p {
line-height: 1.3em;
}
/* Customer login */
.rcue-login-register.customer {
background-image: url("img/customer-login-screen-bg2.jpg");
}
.rcue-login-register p.powered {
font-size: 1.1em;
margin-top: 1.27272727272727em;
@ -402,11 +399,6 @@ a.zocial:before {
.rcue-login-register.email label {
width: 6.78571428571429em;
}
.rcue-login-register.email .form-area.email {
background-position: 40.6em center;
background-image: url(img/login-register-email-separator.svg);
background-repeat: no-repeat;
}
.rcue-login-register.email .feedback.bottom-left {
left: 38.3em;
}

View file

@ -3,7 +3,6 @@
display: inline-block;
width: 16px;
height: 16px;
background-image: url(img/sprites.png); /* Modified by Gabriel */
background-repeat: no-repeat;
text-indent: -99999em;
margin-right: 0.5em;

View file

@ -30,14 +30,6 @@ table thead tr th {
.rcue-table-actions {
padding: 1px;
}
/*
.rcue-table-actions button {
padding: 3px 8px;
font-size: 11px;
box-shadow: 1px 2px 2px #e3e3e3;
margin: 4px;
}
*/
.rcue-table-number {
text-align: right;
width: 100px;
@ -54,11 +46,7 @@ table thead tr th {
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fafafa), color-stop(1, 0, #eeeeee));
border-bottom: 1px #cedede solid;
}
/*
table tbody tr td:first-child {
color: #0099d3;
}
*/
table thead tr th:last-child {
border-right: none;
}
@ -70,12 +58,7 @@ table tbody tr:first-child td {
table tbody tr td:last-child {
border-right: none;
}
/*
table tbody tr:hover {
cursor: pointer;
background-color: #ebebeb;
}
*/
/* Styles from Gabriel */
.rcue-table-actions button + button,
.rcue-table-actions .button + button {
@ -109,23 +92,7 @@ table tbody tr td.token-cell button {
margin-bottom: 7px;
margin-top: 8px;
}
table tbody.selectable-rows tr:hover {
cursor: pointer;
background-color: #ebebeb;
}
table tbody.selectable-rows tr:first-child td {
padding-top: 9px;
}
table tbody.selectable-rows tr.selected,
table tbody.selectable-rows tr.selected:hover {
background-color: #eaf5fb;
}
table tbody.selectable-rows tr.selected td:first-child,
table tbody.selectable-rows tr.selected:hover td:first-child {
background-image: url(img/icon-row-selected.svg);
background-position: 0.2em center;
background-repeat: no-repeat;
}
table tfoot tr {
border-top: 1px solid #cecece;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

View file

@ -15,15 +15,15 @@
</div>
<div class="form-group">
<label for="password-new">${rb.getString('passwordNew')}</label>
<input type="password" id="password-new" name="password-new" placeholder="At least 6 characters" class="error">
<input type="password" id="password-new" name="password-new">
</div>
<div class="form-group">
<label for="password-confirm" class="two-lines">${rb.getString('passwordConfirm')}</label>
<input type="password" id="password-confirm" name="password-confirm" class="error">
<input type="password" id="password-confirm" name="password-confirm">
</div>
</fieldset>
<div class="form-actions">
<a href="#">« Back to my application</a>
<#--a href="#">« Back to my application</a-->
<button type="submit" class="primary">Save</button>
<button type="submit">Cancel</button>
</div>

View file

@ -4,16 +4,15 @@
<head>
<meta charset="utf-8">
<title>Edit Account - <#nested "title"></title>
<!-- TODO replace with actual logo once
<link rel="icon" href="img/favicon.ico">
<!-- Frameworks -->
<link rel="stylesheet" href="${template.formsPath}/theme/${template.theme}/css/reset.css">
<!--link rel="stylesheet" href="bootstrap-3.0.0-wip/css/bootstrap.css"-->
<link href="${template.formsPath}/lib/bootstrap/css/bootstrap.css" rel="stylesheet" />
<link href="${template.formsPath}/theme/${template.theme}/css/zocial/zocial.css" rel="stylesheet">
<link rel="stylesheet" href="${template.formsPath}/theme/${template.theme}/css/sprites.css">
<link rel="stylesheet" href="${template.formsPath}/theme/${template.theme}/css/select2.css">
<!-- TODO remove external links -->
<link rel="stylesheet" href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic'>
@ -21,16 +20,12 @@
<link rel="stylesheet" href="${template.formsPath}/theme/${template.theme}/css/base.css">
<link rel="stylesheet" href="${template.formsPath}/theme/${template.theme}/css/forms.css">
<link rel="stylesheet" href="${template.formsPath}/theme/${template.theme}/css/header.css">
<link rel="stylesheet" href="${template.formsPath}/theme/${template.theme}/css/tabs.css">
<link rel="stylesheet" href="${template.formsPath}/theme/${template.theme}/css/icons.css">
<link rel="stylesheet" href="${template.formsPath}/theme/${template.theme}/css/tables.css">
<!-- Page styles -->
<link rel="stylesheet" href="${template.formsPath}/theme/${template.theme}/css/admin-console.css">
<script src="${template.formsPath}/lib/jquery/jquery-2.0.3.min.js"></script>
<script src="${template.formsPath}/lib/bootstrap/js/bootstrap.js"></script>
</head>
<body class="admin-console user ${bodyClass}">
@ -70,7 +65,7 @@
<li class="<#if active=='password'>active</#if>"><a href="${url.passwordUrl}">Password</a></li>
<li class="<#if active=='totp'>active</#if>"><a href="${url.totpUrl}">Authenticator</a></li>
<#--<li class="<#if active=='social'>active</#if>"><a href="${url.socialUrl}">Social Accounts</a></li>-->
<li class="<#if active=='access'>active</#if>"><a href="${url.accessUrl}">Authorized Access</a></li>
<#--<li class="<#if active=='access'>active</#if>"><a href="${url.accessUrl}">Authorized Access</a></li>-->
</ul>
</div>

View file

@ -62,3 +62,6 @@ emailSent=You should receive an email shortly with further instructions.
emailError=Invalid username or email.
emailErrorInfo=Please, fill in the fields again.
emailInstruction=Enter your username and email address and we will send you instructions on how to create a new password.
accountUpdated=Your account has been updated
accountPasswordUpdated=Your password has been updated

View file

@ -131,12 +131,20 @@ public class AccountService {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processAccountUpdate(final MultivaluedMap<String, String> formData) {
UserModel user = getUser(true);
String error = Validation.validateUpdateProfileForm(formData);
if (error != null) {
return Flows.forms(realm, request, uriInfo).setUser(user).setError(error).forwardToAccount();
}
user.setFirstName(formData.getFirst("firstName"));
user.setLastName(formData.getFirst("lastName"));
user.setEmail(formData.getFirst("email"));
return Flows.forms(realm, request, uriInfo).setUser(user).forwardToAccount();
return Flows.forms(realm, request, uriInfo).setUser(user).setError("accountUpdated")
.setErrorType(FormFlows.MessageType.SUCCESS).forwardToAccount();
}
@Path("totp-remove")
@ -205,7 +213,8 @@ public class AccountService {
realm.updateCredential(user, credentials);
return Flows.forms(realm, request, uriInfo).setUser(user).forwardToPassword();
return Flows.forms(realm, request, uriInfo).setUser(user).setError("accountPasswordUpdated")
.setErrorType(FormFlows.MessageType.SUCCESS).forwardToPassword();
}
@Path("login-redirect")

View file

@ -39,6 +39,8 @@ import org.keycloak.testsuite.rule.KeycloakRule.KeycloakSetup;
import org.keycloak.testsuite.rule.WebResource;
import org.keycloak.testsuite.rule.WebRule;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.picketlink.idm.credential.util.TimeBasedOTP;
/**
@ -96,8 +98,18 @@ public class AccountTest {
changePasswordPage.open();
loginPage.login("test-user@localhost", "password");
changePasswordPage.changePassword("", "new-password", "new-password");
Assert.assertTrue(profilePage.isError());
changePasswordPage.changePassword("password", "new-password", "new-password2");
Assert.assertTrue(profilePage.isError());
changePasswordPage.changePassword("password", "new-password", "new-password");
Assert.assertTrue(profilePage.isSuccess());
changePasswordPage.logout();
loginPage.open();
@ -120,8 +132,31 @@ public class AccountTest {
Assert.assertEquals("", profilePage.getLastName());
Assert.assertEquals("test-user@localhost", profilePage.getEmail());
// All fields are required, so there should be an error when something is missing.
profilePage.updateProfile("", "New last", "new@email.com");
Assert.assertTrue(profilePage.isError());
Assert.assertEquals("", profilePage.getFirstName());
Assert.assertEquals("", profilePage.getLastName());
Assert.assertEquals("test-user@localhost", profilePage.getEmail());
profilePage.updateProfile("New first", "", "new@email.com");
Assert.assertTrue(profilePage.isError());
Assert.assertEquals("", profilePage.getFirstName());
Assert.assertEquals("", profilePage.getLastName());
Assert.assertEquals("test-user@localhost", profilePage.getEmail());
profilePage.updateProfile("New first", "New last", "");
Assert.assertTrue(profilePage.isError());
Assert.assertEquals("", profilePage.getFirstName());
Assert.assertEquals("", profilePage.getLastName());
Assert.assertEquals("test-user@localhost", profilePage.getEmail());
profilePage.updateProfile("New first", "New last", "new@email.com");
Assert.assertTrue(profilePage.isSuccess());
Assert.assertEquals("New first", profilePage.getFirstName());
Assert.assertEquals("New last", profilePage.getLastName());
Assert.assertEquals("new@email.com", profilePage.getEmail());
@ -136,8 +171,15 @@ public class AccountTest {
Assert.assertFalse(driver.getPageSource().contains("Remove Google"));
// Error with false code
totpPage.configure(totp.generate(totpPage.getTotpSecret()+"123"));
Assert.assertTrue(profilePage.isError());
totpPage.configure(totp.generate(totpPage.getTotpSecret()));
Assert.assertTrue(profilePage.isSuccess());
Assert.assertTrue(driver.getPageSource().contains("Remove Google"));
}

View file

@ -44,6 +44,9 @@ public class AccountUpdateProfilePage extends AbstractAccountPage {
@FindBy(css = "button[type=\"submit\"]")
private WebElement submitButton;
@FindBy(css = ".feedback > p > strong")
private WebElement feedbackMessage;
public void updateProfile(String firstName, String lastName, String email) {
firstNameInput.clear();
firstNameInput.sendKeys(firstName);
@ -75,4 +78,11 @@ public class AccountUpdateProfilePage extends AbstractAccountPage {
driver.navigate().to(PATH);
}
public boolean isSuccess(){
return feedbackMessage != null && "Success!".equals(feedbackMessage.getText());
}
public boolean isError(){
return feedbackMessage != null && "Error!".equals(feedbackMessage.getText());
}
}