Skip to content

Commit

Permalink
- refactoring for getSecurityPolicy to search by archetypeOid if spec…
Browse files Browse the repository at this point in the history
…ified

- some work for "no archetype is defined" use case
  • Loading branch information
KaterynaHonchar committed Aug 9, 2023
1 parent 8c5daa9 commit b196211
Show file tree
Hide file tree
Showing 16 changed files with 140 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ protected SecurityPolicyType resolveSecurityPolicy() {
OperationResult result = new OperationResult(OPERATION_GET_SECURITY_POLICY);

try {
return getModelInteractionService().getSecurityPolicy((PrismObject<UserType>) null, task, result);
return getModelInteractionService().getSecurityPolicy((PrismObject<UserType>) null, null, task, result);
} catch (CommonException e) {
LOGGER.error("Could not retrieve security policy: {}", e.getMessage(), e);
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ protected SecurityPolicyType load() {
Task task = createAnonymousTask(OPERATION_LOAD_RESET_PASSWORD_POLICY);
OperationResult parentResult = new OperationResult(OPERATION_LOAD_RESET_PASSWORD_POLICY);
try {
return getModelInteractionService().getSecurityPolicy((PrismObject<? extends FocusType>) null, task, parentResult);
return getModelInteractionService().getSecurityPolicy((PrismObject<? extends FocusType>) null,
getArchetypeOid(), task, parentResult);
} catch (CommonException e) {
LOGGER.warn("Cannot read credentials policy: " + e.getMessage(), e);
}
Expand Down Expand Up @@ -305,7 +306,7 @@ protected SecurityPolicyType resolveSecurityPolicy(PrismObject<UserType> user) {
OperationResult result = new OperationResult(OPERATION_GET_SECURITY_POLICY);

try {
return getModelInteractionService().getSecurityPolicy(user, task, result);
return getModelInteractionService().getSecurityPolicy(user, getArchetypeOid(), task, result);
} catch (CommonException e) {
LOGGER.error("Could not retrieve security policy: {}", e.getMessage(), e);
return null;
Expand All @@ -318,5 +319,8 @@ public MidpointForm<?> getForm() {
return (MidpointForm<?>) get(ID_FORM);
}

protected String getArchetypeOid() {
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<form method="post" wicket:id="form" class="form-horizontal">
<div wicket:id="csrfField"/>
<input type="hidden" wicket:id="archetypeOid"/>
<input type="hidden" wicket:id="allowUndefinedArchetype"/>
<div class="d-flex flex-wrap gap-3 justify-content-center" wicket:id="archetypeSelectionPanel">
<wicket:container wicket:id="archetypes">
<div class="card mb-0 simple-tile selectable" wicket:id="archetype"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
import java.util.List;
import java.util.stream.Collectors;

import org.apache.wicket.AttributeModifier;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;

import com.evolveum.midpoint.web.security.util.SecurityUtils;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.WebMarkupContainer;
Expand Down Expand Up @@ -46,17 +50,20 @@ public class PageArchetypeSelection extends PageAbstractAuthenticationModule<Arc

@Serial private static final long serialVersionUID = 1L;
private static final String DOT_CLASS = PageArchetypeSelection.class.getName() + ".";
private static final Trace LOGGER = TraceManager.getTrace(PageArchetypeSelection.class);
protected static final String OPERATION_LOAD_ARCHETYPE_OBJECTS = DOT_CLASS + "loadArchetypeObjects";
public static final String UNDEFINED_OID = DOT_CLASS + "undefined";
public static final String UNDEFINED_OID = null;

private static final String ID_ARCHETYPE_SELECTION_PANEL = "archetypeSelectionPanel";
private static final String ID_ARCHETYPES_PANEL = "archetypes";
private static final String ID_ARCHETYPE_PANEL = "archetype";
private static final String ID_ARCHETYPE_OID = "archetypeOid";
private static final String ID_ALLOW_UNDEFINED_ARCHETYPE = "allowUndefinedArchetype";

private final IModel<String> archetypeOidModel = Model.of();

private LoadableDetachableModel<ArchetypeSelectionModuleAuthentication> archetypeSelectionModuleModel;
private LoadableModel<List<Tile<ArchetypeType>>> tilesModel;

public PageArchetypeSelection() {
super();
Expand All @@ -77,6 +84,13 @@ protected ArchetypeSelectionModuleAuthentication load() {
return getAuthenticationModuleConfiguration();
}
};

tilesModel = new LoadableModel<List<Tile<ArchetypeType>>>() {
@Override
protected List<Tile<ArchetypeType>> load() {
return loadTilesList();
}
};
}

@Override
Expand All @@ -85,6 +99,10 @@ protected void initModuleLayout(MidpointForm form) {
archetypeOidField.setOutputMarkupId(true);
form.add(archetypeOidField);

HiddenField<Boolean> undefinedArchetypeAllowed = new HiddenField<>(ID_ALLOW_UNDEFINED_ARCHETYPE, Model.of(isUndefinedArchetypeAllowed()));
undefinedArchetypeAllowed.setOutputMarkupId(true);
form.add(undefinedArchetypeAllowed);

initArchetypeSelectionPanel(form);
}

Expand All @@ -98,12 +116,21 @@ protected IModel<String> getLoginPanelDescriptionModel() {
return createStringResource("PageArchetypeSelection.form.description");
}

private boolean isUndefinedArchetypeAllowed() {
var securityPolicy = resolveSecurityPolicy(null);
var loginNameRecoveryModule = SecurityUtils.getArchetypeSelectionAuthModule(securityPolicy);
if (loginNameRecoveryModule == null) {
return false;
}
return Boolean.TRUE.equals(loginNameRecoveryModule.isAllowUndefinedArchetype());
}

private void initArchetypeSelectionPanel(MidpointForm<?> form) {
WebMarkupContainer archetypeSelectionPanel = new WebMarkupContainer(ID_ARCHETYPE_SELECTION_PANEL);
archetypeSelectionPanel.setOutputMarkupId(true);
form.add(archetypeSelectionPanel);

ListView<Tile<ArchetypeType>> archetypeListPanel = new ListView<>(ID_ARCHETYPES_PANEL, loadTilesModel()) {
ListView<Tile<ArchetypeType>> archetypeListPanel = new ListView<>(ID_ARCHETYPES_PANEL, tilesModel) {

@Serial private static final long serialVersionUID = 1L;

Expand All @@ -115,31 +142,23 @@ protected void populateItem(ListItem<Tile<ArchetypeType>> item) {
archetypeSelectionPanel.add(archetypeListPanel);
}

private LoadableModel<List<Tile<ArchetypeType>>> loadTilesModel() {
return new LoadableModel<>(false) {

@Serial private static final long serialVersionUID = 1L;

@Override
protected List<Tile<ArchetypeType>> load() {
List<Tile<ArchetypeType>> tiles = new ArrayList<>();
ArchetypeSelectionModuleAuthentication moduleAuthentication = archetypeSelectionModuleModel.getObject();
var archetypeSelectionType = moduleAuthentication.getArchetypeSelection();
if (archetypeSelectionType == null) {
return tiles;
}
List<ObjectReferenceType> archetypeRefs = archetypeSelectionType.getArchetypeRef();
List<ArchetypeType> archetypes = resolveArchetypeObjects(archetypeRefs);
tiles = archetypes.stream()
.map(archetype -> createTile(archetype))
.collect(Collectors.toList());
if (moduleAuthentication.isAllowUndefined()) {
var undefinedArchetypeTile = createUndefinedArchetypeTile();
tiles.add(undefinedArchetypeTile);
}
return tiles;
}
};
private List<Tile<ArchetypeType>> loadTilesList() {
List<Tile<ArchetypeType>> tiles = new ArrayList<>();
ArchetypeSelectionModuleAuthentication moduleAuthentication = archetypeSelectionModuleModel.getObject();
var archetypeSelectionType = moduleAuthentication.getArchetypeSelection();
if (archetypeSelectionType == null) {
return tiles;
}
List<ObjectReferenceType> archetypeRefs = archetypeSelectionType.getArchetypeRef();
List<ArchetypeType> archetypes = resolveArchetypeObjects(archetypeRefs);
tiles = archetypes.stream()
.map(archetype -> createTile(archetype))
.collect(Collectors.toList());
if (moduleAuthentication.isAllowUndefined()) {
var undefinedArchetypeTile = createUndefinedArchetypeTile();
tiles.add(undefinedArchetypeTile);
}
return tiles;
}

private List<ArchetypeType> resolveArchetypeObjects(List<ObjectReferenceType> archetypeRefs) {
Expand All @@ -152,7 +171,6 @@ private List<ArchetypeType> resolveArchetypeObjects(List<ObjectReferenceType> ar

private Tile<ArchetypeType> createUndefinedArchetypeTile() {
var archetype = new ArchetypeType();
archetype.setOid(UNDEFINED_OID);

var archetypePolicy = new ArchetypePolicyType();

Expand All @@ -166,16 +184,18 @@ private Tile<ArchetypeType> createUndefinedArchetypeTile() {
.label(undefinedArchetypeLabel)
.icon(new IconType().cssClass(CLASS_TEST_CONNECTION_MENU_ITEM))
.help(undefinedArchetypeHelp);
archetypePolicy.setDisplay(archetypeDisplay);
archetype.setArchetypePolicy(archetypePolicy);

return createTile(archetype);
return createTile(archetype, archetypeDisplay);
}


private Tile<ArchetypeType> createTile(ArchetypeType archetype) {
var archetypeDisplayType = GuiDisplayTypeUtil.getArchetypePolicyDisplayType(archetype,
PageArchetypeSelection.this);
return createTile(archetype, archetypeDisplayType);
}

private Tile<ArchetypeType> createTile(ArchetypeType archetype, DisplayType archetypeDisplayType) {
var iconCssClass = GuiDisplayTypeUtil.getIconCssClass(archetypeDisplayType);
var label = GuiDisplayTypeUtil.getTranslatedLabel(archetypeDisplayType);
var help = GuiDisplayTypeUtil.getHelp(archetypeDisplayType);
Expand All @@ -191,27 +211,28 @@ private Component createTilePanel(IModel<Tile<ArchetypeType>> tileModel) {

@Override
protected void onClick(AjaxRequestTarget target) {
updateArchetypeOidField(tileModel, target);
archetypeSelected(tileModel, target);
target.add(getArchetypesContainer());
}
};
tilePanel.add(AttributeModifier.append("class", getActiveClassModel(tileModel.getObject())));
// tilePanel.add(AttributeModifier.append("class", getActiveClassModel(tileModel.getObject())));
return tilePanel;
}

private void updateArchetypeOidField(IModel<Tile<ArchetypeType>> tileModel, AjaxRequestTarget target) {
private void archetypeSelected(IModel<Tile<ArchetypeType>> tileModel, AjaxRequestTarget target) {
archetypeOidModel.setObject(getArchetypeOid(tileModel));
tileModel.getObject().setSelected(true);
target.add(getArchetypeOidField());
}

private String getArchetypeOid(IModel<Tile<ArchetypeType>> tileModel) {
return tileModel.getObject().getValue().getOid();
}

private IModel<String> getActiveClassModel(Tile<ArchetypeType> tile) {
var isArchetypeSelected = tile.getValue().getOid().equals(archetypeOidModel.getObject());
return isArchetypeSelected ? Model.of("active") : Model.of();
}
// private IModel<String> getActiveClassModel(Tile<ArchetypeType> tile) {
// var isArchetypeSelected = tile.getValue().isSelected();
// return isArchetypeSelected ? Model.of("active") : Model.of();
// }

private WebMarkupContainer getArchetypesContainer() {
return (WebMarkupContainer) getForm().get(ID_ARCHETYPE_SELECTION_PANEL);
Expand All @@ -221,4 +242,7 @@ private Component getArchetypeOidField() {
return getForm().get(ID_ARCHETYPE_OID);
}

protected String getArchetypeOid() {
return archetypeOidModel.getObject();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,15 @@

import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.web.component.util.EnableBehaviour;
import com.evolveum.midpoint.web.component.util.VisibleBehaviour;

import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.WebComponent;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

import com.evolveum.midpoint.authentication.api.authorization.PageDescriptor;
import com.evolveum.midpoint.authentication.api.authorization.Url;
import com.evolveum.midpoint.authentication.api.config.CredentialModuleAuthentication;
import com.evolveum.midpoint.authentication.api.config.MidpointAuthentication;
import com.evolveum.midpoint.authentication.api.config.ModuleAuthentication;
import com.evolveum.midpoint.authentication.api.util.AuthUtil;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ public static String getChannelUrlSuffixFromAuthSequence(String sequenceIdentifi
return channel.getUrlSuffix();
}

public static ArchetypeSelectionModuleType getLoginRecoveryAuthModule(SecurityPolicyType securityPolicy) {
public static ArchetypeSelectionModuleType getArchetypeSelectionAuthModule(SecurityPolicyType securityPolicy) {
if (securityPolicy == null || securityPolicy.getAuthentication() == null
|| securityPolicy.getAuthentication().getModules() == null) {
return null;
Expand All @@ -229,17 +229,18 @@ public static ArchetypeSelectionModuleType getLoginRecoveryAuthModule(SecurityPo
return null;
}
List<AuthenticationSequenceModuleType> modules = sequence.getModule();
if (modules.size() == 1) {
//for now only one archetype based module is supported for login recovery functionality
var loginRecoveryModule = modules.get(0);
var recoveryModuleIdentifier = loginRecoveryModule.getIdentifier();
for (AuthenticationSequenceModuleType module : modules) {
var recoveryModuleIdentifier = module.getIdentifier();
List<ArchetypeSelectionModuleType> archetypeBasedModules =
securityPolicy.getAuthentication().getModules().getArchetypeSelection();
return archetypeBasedModules
var archetypeSelectionModule = archetypeBasedModules
.stream()
.filter(m -> m.getIdentifier().equals(recoveryModuleIdentifier))
.findFirst()
.orElse(null);
if (archetypeSelectionModule != null) {
return archetypeSelectionModule;
}
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ private List<SecurityQuestionDefinitionType> getQuestions(PrismObject<UserType>
SecurityPolicyType securityPolicyType;
try {
SecurityContextHolder.getContext().setAuthentication(new AnonymousAuthenticationToken("rest_sec_q_auth", "REST", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")));
securityPolicyType = modelInteractionService.getSecurityPolicy(user, task, result);
securityPolicyType = modelInteractionService.getSecurityPolicy(user, null, task, result);
} catch (ObjectNotFoundException | SchemaException | CommunicationException | ConfigurationException | SecurityViolationException | ExpressionEvaluationException e) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ private SecurityPolicyType loadSecurityPolicyForArchetype(String archetypeOid) {
var operation = "loadSecurityPolicyForArchetype";
Task task = taskManager.createTaskInstance(operation);
OperationResult result = new OperationResult(operation);
return modelInteractionService.getSecurityPolicy(archetypeOid, task, result);
return modelInteractionService.getSecurityPolicy(null, archetypeOid, task, result);
} catch (Exception ex) {
LOGGER.debug("Couldn't load security policy for archetype");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ private SecurityPolicyType resolveSecurityPolicy(MidpointAuthentication mpAuthen
Task task = taskManager.createTaskInstance(operation);
OperationResult result = new OperationResult(operation);
var archetypeOid = mpAuthentication.getArchetypeOid();
return modelInteractionService.getSecurityPolicy(archetypeOid, task, result);
return modelInteractionService.getSecurityPolicy(null, archetypeOid, task, result);
} catch (Exception ex) {
LOGGER.debug("Couldn't load security policy for archetype");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ protected Authentication doAuthenticate(
throw new AuthenticationServiceException("web.security.provider.unavailable");
}

//todo process the case when no archetype oid is defined
var archetypeOid = ((ArchetypeSelectionAuthenticationToken) authentication).getArchetypeOid();
var allowUndefinedArchetype = ((ArchetypeSelectionAuthenticationToken) authentication).isAllowUndefinedArchetype();
if (StringUtils.isEmpty(archetypeOid) && !allowUndefinedArchetype) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,22 +249,14 @@ <F extends FocusType> NonceCredentialsPolicyType determineNonceCredentialsPolicy
throws SchemaException, ExpressionEvaluationException, CommunicationException, SecurityViolationException, ConfigurationException;

<F extends FocusType> SecurityPolicyType getSecurityPolicy(
PrismObject<F> focus, Task task, OperationResult parentResult)
PrismObject<F> focus, String archetypeOid, Task task, OperationResult parentResult)
throws ObjectNotFoundException, SchemaException, CommunicationException,
ConfigurationException, SecurityViolationException, ExpressionEvaluationException;

SecurityPolicyType getSecurityPolicy(ResourceObjectDefinition rOCDef, Task task, OperationResult parentResult)
throws SchemaException, CommunicationException, ConfigurationException,
SecurityViolationException, ExpressionEvaluationException, ObjectNotFoundException;

/**
* Returns security policy for the specified by the oid archetype.
*/
SecurityPolicyType getSecurityPolicy(
String archetypeOid, Task task, OperationResult parentResult)
throws ObjectNotFoundException, SchemaException, CommunicationException,
ConfigurationException, SecurityViolationException, ExpressionEvaluationException;

/**
* Returns an authentications policies as defined in the system configuration security policy. This method is designed to be used
* during registration process or reset password process.
Expand Down

0 comments on commit b196211

Please sign in to comment.