Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@
import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
import org.apache.syncope.client.ui.commons.Constants;
import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
import org.apache.syncope.common.keymaster.client.api.ServiceOps;
import org.apache.syncope.common.lib.to.AuthProfileTO;
import org.apache.syncope.common.lib.types.AMEntitlement;
import org.apache.syncope.common.lib.wa.GoogleMfaAuthAccount;
import org.apache.syncope.common.lib.wa.GoogleMfaAuthToken;
import org.apache.syncope.common.lib.wa.ImpersonationAccount;
import org.apache.syncope.common.lib.wa.MfaTrustedDevice;
import org.apache.syncope.common.lib.wa.WAConsentDecision;
import org.apache.syncope.common.lib.wa.WebAuthnDeviceCredential;
import org.apache.wicket.PageReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
Expand All @@ -66,14 +68,20 @@ public class AuthProfileDirectoryPanel

private static final long serialVersionUID = 2018518567549153364L;

private String keyword;
private final ServiceOps serviceOps;

private final BaseModal<AuthProfileTO> authProfileModal;

private String keyword;

public AuthProfileDirectoryPanel(
final String id, final AuthProfileRestClient restClient, final PageReference pageRef) {
final String id,
final ServiceOps serviceOps,
final AuthProfileRestClient restClient,
final PageReference pageRef) {

super(id, restClient, pageRef);
this.serviceOps = serviceOps;

authProfileModal = new BaseModal<>(Constants.OUTER) {

Expand Down Expand Up @@ -162,6 +170,15 @@ protected boolean isCondition(final IModel<AuthProfileTO> rowModel) {
return CollectionUtils.isNotEmpty(rowModel.getObject().getWebAuthnDeviceCredentials());
}
});
columns.add(new BooleanConditionColumn<>(new StringResourceModel("consentDecisions")) {

private static final long serialVersionUID = -8236820422411536323L;

@Override
protected boolean isCondition(final IModel<AuthProfileTO> rowModel) {
return CollectionUtils.isNotEmpty(rowModel.getObject().getConsentDecisions());
}
});

return columns;
}
Expand All @@ -180,7 +197,7 @@ public void onClick(final AjaxRequestTarget target, final AuthProfileTO ignore)
target.add(authProfileModal.setContent(new ModalDirectoryPanel<>(
authProfileModal,
new AuthProfileItemDirectoryPanel<ImpersonationAccount>(
"panel", restClient, authProfileModal, model.getObject(), pageRef) {
"panel", serviceOps, restClient, authProfileModal, model.getObject(), null, pageRef) {

private static final long serialVersionUID = -5380664539000792237L;

Expand Down Expand Up @@ -227,7 +244,7 @@ public void onClick(final AjaxRequestTarget target, final AuthProfileTO ignore)
target.add(authProfileModal.setContent(new ModalDirectoryPanel<>(
authProfileModal,
new AuthProfileItemDirectoryPanel<GoogleMfaAuthToken>(
"panel", restClient, authProfileModal, model.getObject(), pageRef) {
"panel", serviceOps, restClient, authProfileModal, model.getObject(), null, pageRef) {

private static final long serialVersionUID = 7332357430197837993L;

Expand Down Expand Up @@ -276,7 +293,7 @@ public void onClick(final AjaxRequestTarget target, final AuthProfileTO ignore)
target.add(authProfileModal.setContent(new ModalDirectoryPanel<>(
authProfileModal,
new AuthProfileItemDirectoryPanel<GoogleMfaAuthAccount>(
"panel", restClient, authProfileModal, model.getObject(), pageRef) {
"panel", serviceOps, restClient, authProfileModal, model.getObject(), null, pageRef) {

private static final long serialVersionUID = -670769282358547044L;

Expand Down Expand Up @@ -325,7 +342,7 @@ public void onClick(final AjaxRequestTarget target, final AuthProfileTO ignore)
target.add(authProfileModal.setContent(new ModalDirectoryPanel<>(
authProfileModal,
new AuthProfileItemDirectoryPanel<MfaTrustedDevice>(
"panel", restClient, authProfileModal, model.getObject(), pageRef) {
"panel", serviceOps, restClient, authProfileModal, model.getObject(), null, pageRef) {

private static final long serialVersionUID = 5788448799796630011L;

Expand Down Expand Up @@ -376,7 +393,7 @@ public void onClick(final AjaxRequestTarget target, final AuthProfileTO ignore)
target.add(authProfileModal.setContent(new ModalDirectoryPanel<>(
authProfileModal,
new AuthProfileItemDirectoryPanel<WebAuthnDeviceCredential>(
"panel", restClient, authProfileModal, model.getObject(), pageRef) {
"panel", serviceOps, restClient, authProfileModal, model.getObject(), null, pageRef) {

private static final long serialVersionUID = 6820212423488933184L;

Expand Down Expand Up @@ -415,6 +432,55 @@ protected List<IColumn<WebAuthnDeviceCredential, String>> getColumns() {
}
}, ActionLink.ActionType.HTML, AMEntitlement.AUTH_PROFILE_UPDATE);

panel.add(new ActionLink<>() {

private static final long serialVersionUID = -3722207913631435501L;

@Override
public void onClick(final AjaxRequestTarget target, final AuthProfileTO ignore) {
model.setObject(restClient.read(model.getObject().getKey()));
target.add(authProfileModal.setContent(new ModalDirectoryPanel<>(
authProfileModal,
new AuthProfileItemDirectoryPanel<WAConsentDecision>("panel", serviceOps,
restClient, authProfileModal, model.getObject(), List.of("attributes"), pageRef) {

private static final long serialVersionUID = -670769282358547044L;

@Override
protected List<WAConsentDecision> getItems() {
return model.getObject().getConsentDecisions();
}

@Override
protected WAConsentDecision defaultItem() {
return new WAConsentDecision();
}

@Override
protected String sortProperty() {
return "id";
}

@Override
protected String paginatorRowsKey() {
return AMConstants.PREF_AUTHPROFILE_CONSENT_DECISION_PAGINATOR_ROWS;
}

@Override
protected List<IColumn<WAConsentDecision, String>> getColumns() {
List<IColumn<WAConsentDecision, String>> columns = new ArrayList<>();
columns.add(new PropertyColumn<>(new ResourceModel("id"), "id", "id"));
columns.add(new PropertyColumn<>(new ResourceModel("service"), "service", "service"));
columns.add(new DatePropertyColumn<>(
new ResourceModel("createdDate"), "createdDate", "createdDate"));
return columns;
}
}, pageRef)));
authProfileModal.header(new Model<>(getString("consentDecisions", model)));
authProfileModal.show(true);
}
}, ActionLink.ActionType.ASSIGN, AMEntitlement.AUTH_PROFILE_UPDATE);

panel.add(new ActionLink<>() {

private static final long serialVersionUID = -3722207913631435501L;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.apache.syncope.client.ui.commons.Constants;
import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
import org.apache.syncope.common.keymaster.client.api.ServiceOps;
import org.apache.syncope.common.lib.BaseBean;
import org.apache.syncope.common.lib.to.AuthProfileTO;
import org.apache.syncope.common.lib.types.AMEntitlement;
Expand All @@ -60,9 +61,11 @@ public abstract class AuthProfileItemDirectoryPanel<I extends BaseBean>

public AuthProfileItemDirectoryPanel(
final String id,
final ServiceOps serviceOps,
final AuthProfileRestClient restClient,
final BaseModal<AuthProfileTO> authProfileModal,
final AuthProfileTO authProfile,
final List<String> excluded,
final PageReference pageRef) {

super(id, restClient, pageRef, false);
Expand All @@ -75,6 +78,8 @@ public AuthProfileItemDirectoryPanel(
enableUtilityButton();
setFooterVisibility(false);

addNewItemPanelBuilder(new AuthProfileItemWizardBuilder(excluded, serviceOps, restClient, pageRef), false);

disableCheckBoxes();
initResultTable();
}
Expand Down Expand Up @@ -179,8 +184,13 @@ protected class AuthProfileItemWizardBuilder extends AuthProfileWizardBuilder<I>

private static final long serialVersionUID = -7174537333960225216L;

protected AuthProfileItemWizardBuilder(final PageReference pageRef) {
super(defaultItem(), new StepModel<>(), pageRef);
protected AuthProfileItemWizardBuilder(
final List<String> excluded,
final ServiceOps serviceOps,
final AuthProfileRestClient authProfileRestClient,
final PageReference pageRef) {

super(defaultItem(), new StepModel<>(), excluded, serviceOps, authProfileRestClient, pageRef);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.apache.syncope.client.console.commons.KeywordSearchEvent;
import org.apache.syncope.client.console.rest.AuthProfileRestClient;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
import org.apache.syncope.common.keymaster.client.api.ServiceOps;
import org.apache.wicket.PageReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
Expand All @@ -37,6 +38,7 @@ public class AuthProfilePanel extends Panel {

public AuthProfilePanel(
final String id,
final ServiceOps serviceOps,
final AuthProfileRestClient authProfileRestClient,
final PageReference pageRef) {

Expand Down Expand Up @@ -66,6 +68,7 @@ protected void onSubmit(final AjaxRequestTarget target) {
form.add(search);
form.setDefaultButton(search);

add(new AuthProfileDirectoryPanel("authProfiles", authProfileRestClient, pageRef).setOutputMarkupId(true));
add(new AuthProfileDirectoryPanel("authProfiles", serviceOps, authProfileRestClient, pageRef).
setOutputMarkupId(true));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@
*/
package org.apache.syncope.client.console.authprofiles;

import java.util.List;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.syncope.client.console.panels.BeanPanel;
import org.apache.syncope.client.console.rest.AuthProfileRestClient;
import org.apache.syncope.client.console.wicket.markup.html.form.JsonEditorPanel;
import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
import org.apache.syncope.common.keymaster.client.api.ServiceOps;
import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
import org.apache.syncope.common.lib.BaseBean;
import org.apache.syncope.common.lib.wa.WAConsentDecision;
import org.apache.wicket.PageReference;
import org.apache.wicket.extensions.wizard.WizardModel;
import org.apache.wicket.extensions.wizard.WizardStep;
Expand All @@ -33,14 +39,33 @@

protected final StepModel<T> model;

public AuthProfileWizardBuilder(final T defaultItem, final StepModel<T> model, final PageReference pageRef) {
protected final List<String> excluded;

protected final ServiceOps serviceOps;

protected final AuthProfileRestClient authProfileRestClient;

public AuthProfileWizardBuilder(
final T defaultItem,
final StepModel<T> model,
final List<String> excluded,
final ServiceOps serviceOps,
final AuthProfileRestClient authProfileRestClient,
final PageReference pageRef) {

super(defaultItem, pageRef);
this.model = model;
this.excluded = excluded;
this.serviceOps = serviceOps;
this.authProfileRestClient = authProfileRestClient;
}

@Override
protected WizardModel buildModelSteps(final T modelObject, final WizardModel wizardModel) {
wizardModel.add(new Step(modelObject));
if (modelObject instanceof WAConsentDecision consentDecision) {
wizardModel.add(new ConsentAttributes(consentDecision));
}
return wizardModel;
}

Expand All @@ -66,7 +91,32 @@
Step(final T modelObject) {
model.setObject(modelObject);
model.setInitialModelObject(modelObject);
add(new BeanPanel<>("bean", model, pageRef).setRenderBodyOnly(true));
add(new BeanPanel<>("bean", model, pageRef, excluded == null ? null : excluded.toArray(String[]::new)).
setRenderBodyOnly(true));
}
}

protected class ConsentAttributes extends WizardStep {

Check notice

Code scanning / CodeQL

Inner class could be static Note

ConsentAttributes could be made static, since the enclosing instance is used only in its constructor.
Comment thread
ilgrosso marked this conversation as resolved.
Dismissed

private static final long serialVersionUID = -4865650799450548351L;

ConsentAttributes(final WAConsentDecision consentDecision) {
String attributes = "{}";
try {
attributes = authProfileRestClient.readConsentAttributes(
serviceOps.get(NetworkService.Type.WA),
consentDecision.getPrincipal(),
consentDecision.getId());
} catch (Exception e) {
LOG.error("While attempting to fetch consent attributes for principal {} and id {}",
consentDecision.getPrincipal(), consentDecision.getId(), e);
}
add(new JsonEditorPanel(null, Model.of(attributes), true, pageRef));
}

@Override
public String getTitle() {
return getString("attributes");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ public final class AMConstants {
public static final String PREF_AUTHPROFILE_WEBAUTHNDEVICECREDENTIALS_PAGINATOR_ROWS =
"authprofile.webAuthnDeviceCredentials.paginator.rows";

public static final String PREF_AUTHPROFILE_CONSENT_DECISION_PAGINATOR_ROWS =
"authprofile.consentDecisions.paginator.rows";

public static final String PREF_OIDC_CUSTOMSCOPES_PAGINATOR_ROWS = "oidc.customScopes.paginator.rows";

private AMConstants() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ public Panel getPanel(final String panelId) {

@Override
public Panel getPanel(final String panelId) {
return new AuthProfilePanel(panelId, authProfileRestClient, getPageReference());
return new AuthProfilePanel(panelId, serviceOps, authProfileRestClient, getPageReference());
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,17 @@
*/
package org.apache.syncope.client.console.rest;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.json.JsonMapper;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.commons.lang3.Strings;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.syncope.client.console.SyncopeWebApplication;
import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
import org.apache.syncope.common.lib.to.AuthProfileTO;
import org.apache.syncope.common.rest.api.beans.AuthProfileQuery;
import org.apache.syncope.common.rest.api.service.AuthProfileService;
Expand All @@ -27,6 +37,8 @@ public class AuthProfileRestClient extends BaseRestClient {

private static final long serialVersionUID = -7379778542101161274L;

protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();

public long count(final String keyword) {
return getService(AuthProfileService.class).
search(new AuthProfileQuery.Builder().page(1).size(0).keyword(keyword).build()).
Expand All @@ -50,4 +62,32 @@ public void update(final AuthProfileTO authProfile) {
public void delete(final String key) {
getService(AuthProfileService.class).delete(key);
}

public String readConsentAttributes(final NetworkService service, final String principal, final long id)
throws IOException {

Response response = WebClient.create(
Strings.CS.appendIfMissing(service.getAddress(), "/") + "actuator/attributeConsent/" + principal,
List.of(),
SyncopeWebApplication.get().getAnonymousUser(),
SyncopeWebApplication.get().getAnonymousKey(),
null).accept(MediaType.APPLICATION_JSON_TYPE).get();
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
JsonNode nodes = MAPPER.readTree((InputStream) response.getEntity());
for (JsonNode node : nodes) {
if (node.has("decision")) {
JsonNode decision = node.get("decision");
if (decision.has("id") && id == decision.get("id").asLong()) {
if (node.has("attributes")) {
return node.get("attributes").toPrettyString();
}
}
}
}
} else {
LOG.error("While contacting the /actuator/attributeConsent endpoint: HTTP {}", response.getStatus());
}

return "{}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,9 @@ recordDate=Record Date
mfaTrustedDevices=MFA Devices
down.title=mfa devices
down.class=fas fa-barcode
consentDecisions=Consent Decisions
service=Client Application
createdDate=Created Date
assign.title=consent decisions
assign.class=fa-solid fa-clipboard-list
attributes=Attributes
Loading
Loading