pl.edu.icm.unity.oauth.as.console.OAuthEditorClientsTab Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of unity-server-oauth Show documentation
Show all versions of unity-server-oauth Show documentation
Client and server OAuth support
The newest version!
/*
* Copyright (c) 2021 Bixbit - Krzysztof Benedyczak. All rights reserved.
* See LICENCE.txt file for licensing information.
*/
package pl.edu.icm.unity.oauth.as.console;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.accordion.AccordionPanel;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.customfield.CustomField;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.select.Select;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.ValidationResult;
import com.vaadin.flow.function.SerializablePredicate;
import io.imunity.vaadin.elements.LinkButton;
import io.imunity.vaadin.elements.NotificationPresenter;
import io.imunity.vaadin.elements.grid.GridWithActionColumn;
import io.imunity.vaadin.elements.grid.SingleActionHandler;
import io.imunity.vaadin.endpoint.common.api.SubViewSwitcher;
import io.imunity.vaadin.auth.services.DefaultServiceDefinition;
import io.imunity.vaadin.auth.services.ServiceEditorBase;
import io.imunity.vaadin.auth.services.ServiceEditorComponent;
import io.imunity.vaadin.auth.services.idp.GroupWithIndentIndicator;
import io.imunity.vaadin.auth.services.idp.MandatoryGroupSelection;
import io.imunity.vaadin.auth.services.tabs.GroupedValuesChipsWithDropdown;
import io.imunity.vaadin.auth.services.tabs.WebServiceAuthenticationTab;
import pl.edu.icm.unity.base.authn.AuthenticationFlowDefinition;
import pl.edu.icm.unity.base.group.Group;
import pl.edu.icm.unity.base.message.MessageSource;
import pl.edu.icm.unity.engine.api.authn.AuthenticatorInfo;
import pl.edu.icm.unity.engine.api.config.UnityServerConfiguration;
import pl.edu.icm.unity.oauth.as.console.OAuthClient.OAuthClientsBean;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import static io.imunity.vaadin.elements.CSSVars.TEXT_FIELD_BIG;
import static io.imunity.vaadin.elements.CssClassNames.MEDIUM_VAADIN_FORM_ITEM_LABEL;
/**
* OAuth service editor clients tab.
*
* @author P.Piernik
*
*/
class OAuthEditorClientsTab extends VerticalLayout implements ServiceEditorBase.EditorTab
{
private final MessageSource msg;
private final UnityServerConfiguration serverConfig;
private final SubViewSwitcher subViewSwitcher;
private final NotificationPresenter notificationPresenter;
private Binder oauthTokenBinder;
private Binder configBinder;
private Binder clientsBinder;
private final List allRealms;
private final List flows;
private final List authenticators;
private final List allUsernames;
private final Supplier> scopesSupplier;
private List groups;
private MandatoryGroupSelection groupCombo;
OAuthEditorClientsTab(MessageSource msg, UnityServerConfiguration serverConfig,
SubViewSwitcher subViewSwitcher,
List flows, List authenticators,
List allRealms, List allUsernames, Supplier> scopesSupplier, String binding,
NotificationPresenter notificationPresenter)
{
this.subViewSwitcher = subViewSwitcher;
this.msg = msg;
this.serverConfig = serverConfig;
this.allRealms = allRealms;
this.flows = WebServiceAuthenticationTab.filterBindingCompatibleAuthenticationFlow(flows, authenticators, binding);
this.authenticators = authenticators.stream().filter(a -> a.getSupportedBindings().contains(binding))
.map(AuthenticatorInfo::getId).collect(Collectors.toList());
this.allUsernames = allUsernames;
this.scopesSupplier = scopesSupplier;
this.notificationPresenter = notificationPresenter;
}
void initUI(List groups, Binder oauthTokenBinder,
Binder configBinder, Binder clientsBinder)
{
this.groups = groups;
this.oauthTokenBinder = oauthTokenBinder;
this.configBinder = configBinder;
this.clientsBinder = clientsBinder;
setPadding(false);
VerticalLayout mainLayout = new VerticalLayout();
mainLayout.setPadding(false);
mainLayout.add(buildClientsSection());
mainLayout.add(buildAuthenticationSection());
add(mainLayout);
}
private Component buildClientsSection()
{
VerticalLayout mainClientLayout = new VerticalLayout();
mainClientLayout.setPadding(false);
ClientsComponent clients = new ClientsComponent();
VerticalLayout clientsWrapper = new VerticalLayout();
clientsWrapper.setPadding(false);
clientsWrapper.add(clients);
FormLayout comboWrapper = new FormLayout();
groupCombo = new MandatoryGroupSelection(msg);
groupCombo.setWidth(TEXT_FIELD_BIG.value());
groupCombo.setItems(groups);
groupCombo.setRequiredIndicatorVisible(false);
configBinder.forField(groupCombo).bind("clientGroup");
groupCombo.addValueChangeListener(e -> {
clients.filterGroup(e.getValue().group().toString());
});
groupCombo.setGroupChangeConfirmationQuestion(
msg.getMessage("OAuthEditorClientsTab.groupChangeConfirmationQuestion"));
comboWrapper.addFormItem(groupCombo, msg.getMessage("OAuthEditorClientsTab.clientsGroup"));
mainClientLayout.add(comboWrapper);
mainClientLayout.add(clientsWrapper);
clientsBinder.forField(clients).bind("clients");
return mainClientLayout;
}
private Component buildAuthenticationSection()
{
FormLayout mainAuthenticationLayout = new FormLayout();
mainAuthenticationLayout.addClassName(MEDIUM_VAADIN_FORM_ITEM_LABEL.getName());
mainAuthenticationLayout.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 1));
Select realm = new Select<>();
realm.setItems(allRealms);
realm.setEmptySelectionAllowed(false);
oauthTokenBinder.forField(realm).asRequired().bind("realm");
mainAuthenticationLayout.addFormItem(realm, msg.getMessage("ServiceEditorBase.realm"));
Map> labels = new HashMap<>();
labels.put(msg.getMessage("ServiceEditorBase.flows"), flows);
labels.put(msg.getMessage("ServiceEditorBase.authenticators"), authenticators);
GroupedValuesChipsWithDropdown authAndFlows = new GroupedValuesChipsWithDropdown(labels);
oauthTokenBinder.forField(authAndFlows).withValidator((v, c) -> {
if (v == null || v.isEmpty())
{
return ValidationResult.error(msg.getMessage("fieldRequired"));
}
return ValidationResult.ok();
})
.withConverter(List::copyOf, HashSet::new)
.bind(DefaultServiceDefinition::getAuthenticationOptions, DefaultServiceDefinition::setAuthenticationOptions);
authAndFlows.setRequiredIndicatorVisible(true);
mainAuthenticationLayout.addFormItem(authAndFlows, msg.getMessage("ServiceEditorBase.authenticatorsAndFlows"));
AccordionPanel authSection = new AccordionPanel(
msg.getMessage("OAuthEditorClientsTab.authentication"), mainAuthenticationLayout);
authSection.setOpened(true);
return authSection;
}
public void refreshGroups()
{
groupCombo.refreshCaptions();
}
@Override
public VaadinIcon getIcon()
{
return VaadinIcon.BULLETS;
}
@Override
public String getType()
{
return ServiceEditorComponent.ServiceEditorTab.CLIENTS.toString();
}
@Override
public Component getComponent()
{
return this;
}
@Override
public String getCaption()
{
return msg.getMessage("IdpServiceEditorBase.clients");
}
private class ClientsComponent extends CustomField>
{
private final SerializablePredicate removedFilter = c -> !c.isToRemove();
private GridWithActionColumn clientsList;
private String group;
public ClientsComponent()
{
setWidthFull();
initUI();
}
@Override
protected List generateModelValue()
{
return getValue();
}
@Override
protected void setPresentationValue(List oAuthClients)
{
setValue(oAuthClients);
}
private void initUI()
{
VerticalLayout main = new VerticalLayout();
main.setPadding(false);
main.setSpacing(false);
main.setWidthFull();
Button add = new Button(msg.getMessage("create"));
add.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
add.addClickListener(e -> gotoNew());
add.setIcon(VaadinIcon.PLUS_CIRCLE_O.create());
main.add(add);
main.setAlignItems(Alignment.END);
clientsList = new GridWithActionColumn<>(msg::getMessage, getActionsHandlers());
clientsList.setWidthFull();
clientsList.setAllRowsVisible(true);
clientsList.addComponentColumn(
p -> new LinkButton(p.getName(), e -> gotoEdit(p))
).setHeader(msg.getMessage("ClientsComponent.name"));
clientsList.addColumn(OAuthClient::getType)
.setHeader(msg.getMessage("ClientsComponent.type"))
.setAutoWidth(true);
clientsList.addColumn(p -> p.getFlows() != null ? String.join(",", p.getFlows()) : "")
.setHeader(msg.getMessage("ClientsComponent.enabledGrants"))
.setAutoWidth(true);
clientsList.addFilter(removedFilter);
main.add(clientsList);
add(main);
}
private List> getActionsHandlers()
{
SingleActionHandler edit = SingleActionHandler.builder4Edit(msg::getMessage, OAuthClient.class)
.withHandler(r -> {
OAuthClient edited = r.iterator().next();
gotoEdit(edited);
}
).build();
SingleActionHandler remove = SingleActionHandler
.builder4Delete(msg::getMessage, OAuthClient.class).withHandler(r -> {
OAuthClient client = r.iterator().next();
if (client.getEntity() == null)
{
clientsList.removeElement(client);
} else
{
client.setToRemove(true);
}
filterGroup(group);
fireChange();
}).build();
return Arrays.asList(edit, remove);
}
private void gotoNew()
{
gotoEditSubView(null, c -> {
subViewSwitcher.exitSubViewAndShowUpdateInfo();
c.setGroup(group);
clientsList.addElement(c);
});
}
private void gotoEdit(OAuthClient edited)
{
gotoEditSubView(edited, c -> {
c.setUpdated(true);
clientsList.replaceElement(edited, c);
subViewSwitcher.exitSubViewAndShowUpdateInfo();
});
}
private void gotoEditSubView(OAuthClient edited, Consumer onConfirm)
{
EditOAuthClientSubView subView = new EditOAuthClientSubView(msg, serverConfig,
getClientsIds(edited), scopesSupplier, edited, c -> {
onConfirm.accept(c);
fireChange();
clientsList.focus();
}, () -> {
subViewSwitcher.exitSubView();
clientsList.focus();
}, notificationPresenter);
subViewSwitcher.goToSubView(subView);
}
private Set getClientsIds(OAuthClient edited)
{
Set clients = new HashSet<>();
clients.addAll(clientsList.getElements().stream().filter(c -> c.getEntity() == null)
.map(OAuthClient::getId).collect(Collectors.toSet()));
clients.addAll(allUsernames);
if (edited != null)
{
clients.remove(edited.getId());
}
return clients;
}
@Override
public List getValue()
{
return clientsList.getElements();
}
@Override
public void setValue(List value)
{
clientsList.setItems(value);
}
private void fireChange()
{
fireEvent(new ComponentValueChangeEvent<>(this, this, clientsList.getElements(), true));
}
public void filterGroup(String path)
{
group = path;
clientsList.clearFilters();
clientsList.addFilter(removedFilter);
clientsList.addFilter(c -> c.getGroup().equals(path));
}
}
public void addGroupValueChangeListener(Consumer listener)
{
groupCombo.addValueChangeListener(event -> listener.accept(event.getValue()));
}
public List getActiveClients()
{
return clientsBinder.getBean().getClients().stream().filter(
c -> !c.isToRemove() && c.getGroup().equals(groupCombo.getValue().group().toString()))
.collect(Collectors.toList());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy