Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Evolveum/midpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
KaterynaHonchar committed Feb 2, 2021
2 parents 5e3e647 + 520742b commit 56e6275
Show file tree
Hide file tree
Showing 80 changed files with 2,412 additions and 375 deletions.
5 changes: 5 additions & 0 deletions gui/admin-gui/pom.xml
Expand Up @@ -124,6 +124,11 @@
<artifactId>ionicons</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.evolveum.webjars</groupId>
<artifactId>password-score</artifactId>
<scope>runtime</scope>
</dependency>

<!-- WRO4J-->
<dependency>
Expand Down
Expand Up @@ -7,11 +7,70 @@

<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<wicket:head>
<script type="text/javascript" src="js/bootstrap-strength-meter/bootstrap-strength-meter.js" ></script>
<script type="text/javascript" >
function initPasswordValidation() {
$('#password-input').removeAttr("onfocus");
$(document).ready(function() {
$('#password-input').strengthMeter('progressBar', {
container: $('#progress-bar-container')
});
});

$(document).ready(function (){
$("#password-input").passwordValidatorPopover("#password-input", $("#password-validator-popover"), true);
});
};
</script>
</wicket:head>
<wicket:panel>
<span wicket:id="linkContainer" class="col-xs-10 col-lg-11 col-md-10"><span wicket:id="passwordSet"/><span wicket:id="passwordRemove"/> <span class="btn-group" style="float:right"><a href="#" wicket:id="changePasswordLink" class="btn btn-primary btn-xs"></a></span></span>
<span wicket:id="linkContainer" class="col-xs-10 col-lg-11 col-md-10">
<span wicket:id="passwordSet"/>
<span wicket:id="passwordRemove"/>
<span class="btn-group" style="float:right">
<a href="#" wicket:id="changePasswordLink" class="btn btn-primary btn-xs"></a>
</span>
</span>
<div wicket:id="inputContainer">
<input class="form-control input-sm" wicket:id="password1" wicket:message="placeholder:PasswordPanel.passwordPlaceholder" type="password" autocomplete="new-password" about="password1"/>
<input class="form-control input-sm" wicket:id="password2" wicket:message="placeholder:PasswordPanel.repeatPasswordPlaceholder" type="password" autocomplete="new-password" style="margin-top: 5px; margin-bottom: 5px;" about="password2"/>
<div class="password-parent" style="height:30px; position: relative;">
<div class="col-md-12" style="padding: 0px !important;">
<input id="password-input" class="form-control input-sm" wicket:id="password1" wicket:message="placeholder:PasswordPanel.passwordPlaceholder"
type="password" autocomplete="new-password" about="password1" style="padding-right: 26px;" onfocus="initPasswordValidation()"/>
<div id="password-validator-popover" wicket:id="validationContainer">
<div class="arrow-up" />
<div class="popover-inner">
<div>
<ul class="list-group" wicket:id="validationParentItems">
<li class="list-group-item" wicket:id="validationItems" style="display: flex;">
<div wicket:id="validationItem"></div>
</li>
<!-- <li class="list-group-item list-group-item-success">At least 1 lowercase letter</li>-->
<!-- <li class="list-group-item list-group-item-danger">At least 1 uppercase letter</li>-->
<!-- <li class="list-group-item">At least 1 numerical number</li>-->
<!-- <li class="list-group-item">At least 1 special character</li>-->
</ul>
</div>
</div>
</div>
</div>
<div style="position: absolute; right: 8px; top: 8px; z-index: 5;">
<i class="fa fa-eye" style="float:right;cursor: pointer; color: #555555;" onclick="showPassword(this)"></i>
</div>
</div>
<div class="password-progress-bar">
<div class="progress">
<div id="progress-bar-container" class="progress-bar" role="progressbar"/>
</div>
</div>
<div class="password-parent" style="height:30px; position: relative;">
<div class="col-md-12" style="padding: 0px !important;">
<input class="form-control input-sm" wicket:id="password2" wicket:message="placeholder:PasswordPanel.repeatPasswordPlaceholder" type="password" autocomplete="new-password" style="padding-right: 26px;" about="password2"/>
</div>
<div style="position: absolute; right: 8px; top: 8px; z-index: 5;">
<i class="fa fa-eye" style="float:right;cursor: pointer; color: #555555;" onclick="showPassword(this)"></i>
</div>
</div>
</div>
<div wicket:id="removeButtonContainer" class="col-lg-1 col-md-2 col-xs-2" style="float:right; padding-right:0px;"><span class="btn-group" style="float:right;"><a href="#" wicket:id="removePasswordLink" class="btn btn-primary btn-xs"></a></span></div>
</wicket:panel>
Expand Down
Expand Up @@ -6,23 +6,46 @@
*/
package com.evolveum.midpoint.gui.api.component.password;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;

import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils;
import com.evolveum.midpoint.model.api.validator.StringLimitationResult;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.component.breadcrumbs.Breadcrumb;
import com.evolveum.midpoint.web.component.search.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.Application;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxChannel;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.attributes.ThrottlingSettings;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.util.time.Duration;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.IValidator;
import org.apache.wicket.validation.ValidationError;
Expand All @@ -31,7 +54,6 @@
import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.prism.crypto.EncryptionException;
import com.evolveum.midpoint.prism.crypto.Protector;
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.web.component.prism.InputPanel;
import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour;
import com.evolveum.midpoint.web.page.admin.PageAdminFocus;
Expand All @@ -42,12 +64,16 @@
import com.evolveum.midpoint.web.security.MidPointApplication;
import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType;

import org.jfree.util.Log;

/**
* @author lazyman
*/
public class PasswordPanel extends InputPanel {
private static final long serialVersionUID = 1L;

private static final Trace LOGGER = TraceManager.getTrace(PasswordPanel.class);

private static final String ID_LINK_CONTAINER = "linkContainer";
private static final String ID_PASSWORD_SET = "passwordSet";
private static final String ID_PASSWORD_REMOVE = "passwordRemove";
Expand All @@ -57,21 +83,43 @@ public class PasswordPanel extends InputPanel {
private static final String ID_INPUT_CONTAINER = "inputContainer";
private static final String ID_PASSWORD_ONE = "password1";
private static final String ID_PASSWORD_TWO = "password2";
private static final String ID_VALIDATION_CONTAINER = "validationContainer";
private static final String ID_VALIDATION_PARENT_ITEMS = "validationParentItems";
private static final String ID_VALIDATION_ITEMS = "validationItems";
private static final String ID_VALIDATION_ITEM = "validationItem";

private boolean passwordInputVisible;
private static boolean clearPasswordInput = false;
private static boolean setPasswordInput = false;
private final PageBase pageBase;

public PasswordPanel(String id, IModel<ProtectedStringType> model) {
this(id, model, false, model == null || model.getObject() == null);
}

public PasswordPanel(String id, IModel<ProtectedStringType> model, boolean isReadOnly, boolean isInputVisible) {
public <F extends FocusType> PasswordPanel(String id, IModel<ProtectedStringType> model, PrismObject<F> object,
PageBase pageBase) {
this(id, model, false, model == null || model.getObject() == null, object, pageBase);
}

public <F extends FocusType> PasswordPanel(String id, IModel<ProtectedStringType> model, boolean isReadOnly, boolean isInputVisible) {
this(id, model,isReadOnly,isInputVisible, null, null);
}

public <F extends FocusType> PasswordPanel(String id, IModel<ProtectedStringType> model, boolean isReadOnly, boolean isInputVisible,
PrismObject<F> object, PageBase pageBase) {
super(id);
this.passwordInputVisible = isInputVisible;
initLayout(model, isReadOnly);
this.pageBase = pageBase;
initLayout(model, isReadOnly, object);
}

private void initLayout(final IModel<ProtectedStringType> model, final boolean isReadOnly) {
@Override
protected void onInitialize() {
super.onInitialize();
}

private <F extends FocusType> void initLayout(final IModel<ProtectedStringType> model, final boolean isReadOnly, PrismObject<F> object) {
setOutputMarkupId(true);
final WebMarkupContainer inputContainer = new WebMarkupContainer(ID_INPUT_CONTAINER) {
private static final long serialVersionUID = 1L;
Expand All @@ -84,6 +132,82 @@ public boolean isVisible() {
inputContainer.setOutputMarkupId(true);
add(inputContainer);

PrismObject<ValuePolicyType> valuePolicy = null;
try {
if (object != null) {
Task task = getPageBase().createSimpleTask("load value policy");
CredentialsPolicyType credentials = getPageBase().getModelInteractionService().getCredentialsPolicy(object, task, task.getResult());
if (credentials != null && credentials.getPassword() != null
&& credentials.getPassword().getValuePolicyRef() != null) {
valuePolicy = WebModelServiceUtils.resolveReferenceNoFetch(
credentials.getPassword().getValuePolicyRef(), getPageBase(), task, task.getResult());

}
}
} catch (Exception e) {
LOGGER.warn("Couldn't load security policy for focus " + object, e);
}

PrismObject<ValuePolicyType> finalValuePolicy = valuePolicy;
LoadableModel<List<StringLimitationResult>> limitationsModel = new LoadableModel<>() {
@Override
protected List<StringLimitationResult> load() {
if (finalValuePolicy != null && object != null) {
Task task = getPageBase().createSimpleTask("validation of password");
try {
ProtectedStringType newValue = !setPasswordInput ? new ProtectedStringType() : model.getObject();
return getPageBase().getModelInteractionService().validateValue(
newValue, finalValuePolicy.asObjectable(), object, task, task.getResult());
} catch (Exception e) {
LOGGER.error("Couldn't validate password security policy", e);
}
}
return new ArrayList<>();
}
};

final WebMarkupContainer validationContainer = new WebMarkupContainer(ID_VALIDATION_CONTAINER) {
private static final long serialVersionUID = 1L;

@Override
public boolean isVisible() {
return !limitationsModel.getObject().isEmpty();
}
};
validationContainer.setOutputMarkupId(true);
inputContainer.add(validationContainer);

final WebMarkupContainer validationParentContainer = new WebMarkupContainer(ID_VALIDATION_PARENT_ITEMS) {
private static final long serialVersionUID = 1L;

@Override
public boolean isVisible() {
return !limitationsModel.getObject().isEmpty();
}
};
validationParentContainer.setOutputMarkupId(true);
validationContainer.add(validationParentContainer);

ListView<StringLimitationResult> validationItems = new ListView<>(ID_VALIDATION_ITEMS, limitationsModel) {

private static final long serialVersionUID = 1L;

@Override
protected void populateItem(ListItem<StringLimitationResult> item) {
StringLimitationPanel limitationPanel = new StringLimitationPanel(ID_VALIDATION_ITEM, item.getModel());
limitationPanel.setOutputMarkupId(true);
item.add(limitationPanel);
item.add(AttributeModifier.append("class", new IModel<String>() {
@Override
public String getObject() {
return Boolean.TRUE.equals(item.getModelObject().isSuccess()) ? "list-group-item-success" : "";
}
}));
}
};
validationItems.setOutputMarkupId(true);
validationParentContainer.add(validationItems);

final PasswordTextField password1 = new SecureModelPasswordTextField(ID_PASSWORD_ONE, new PasswordModel(model)) {
private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -120,7 +244,24 @@ protected void onUpdate(AjaxRequestTarget target) {
// target.appendJavaScript("$(\"#"+ password2.getMarkupId() +"\").focus()");
}
});
password2.add(new PasswordValidator(password1));
password1.add(new AjaxFormComponentUpdatingBehavior("keyup") {
private static final long serialVersionUID = 1L;

@Override
protected void onUpdate(AjaxRequestTarget target) {
limitationsModel.reset();
target.add(validationParentContainer);
}

@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.setThrottlingSettings(new ThrottlingSettings(Duration.milliseconds(500), true));
attributes.setChannel(new AjaxChannel("Drop", AjaxChannel.Type.DROP));
}
});
password2.add
(new PasswordValidator(password1));

final WebMarkupContainer linkContainer = new WebMarkupContainer(ID_LINK_CONTAINER) {
private static final long serialVersionUID = 1L;
Expand All @@ -147,6 +288,7 @@ public boolean isVisible() {
@Override
public void onClick(AjaxRequestTarget target) {
clearPasswordInput = true;
setPasswordInput = false;
onLinkClick(target);
}

Expand Down Expand Up @@ -183,7 +325,7 @@ public void onClick(AjaxRequestTarget target) {

@Override
public boolean isVisible() {
PageBase pageBase = (PageBase) getPage();
PageBase pageBase = getPageBase();
if (pageBase == null) {
return false;
}
Expand All @@ -204,6 +346,10 @@ public boolean isVisible() {
add(removeButtonContainer);
}

private PageBase getPageBase() {
return pageBase;
}

private void onLinkClick(AjaxRequestTarget target) {
passwordInputVisible = true;
target.add(this);
Expand Down Expand Up @@ -304,8 +450,10 @@ public String getObject() {
public void setObject(String object) {
if (clearPasswordInput) {
clearPasswordInput = false;
setPasswordInput = false;
return;
}
setPasswordInput = true;
if (object == null) {
psModel.setObject(null);
} else {
Expand Down

0 comments on commit 56e6275

Please sign in to comment.