Skip to content

Commit

Permalink
cluster-wide support for session management - MID-5650
Browse files Browse the repository at this point in the history
  • Loading branch information
katkav committed Sep 6, 2019
1 parent c023c65 commit b8b56dd
Show file tree
Hide file tree
Showing 43 changed files with 729 additions and 261 deletions.
11 changes: 11 additions & 0 deletions gui/admin-gui/pom.xml
Expand Up @@ -174,6 +174,17 @@
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>

<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<scope>compile</scope>
</dependency>

<!-- webjars -->
<dependency>
<groupId>org.webjars</groupId>
Expand Down
Expand Up @@ -77,6 +77,7 @@
import com.evolveum.midpoint.security.api.SecurityContextManager;
import com.evolveum.midpoint.security.enforcer.api.AuthorizationParameters;
import com.evolveum.midpoint.security.enforcer.api.SecurityEnforcer;
import com.evolveum.midpoint.task.api.ClusterExecutionHelper;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.task.api.TaskCategory;
import com.evolveum.midpoint.task.api.TaskManager;
Expand Down Expand Up @@ -335,6 +336,8 @@ public abstract class PageBase extends WebPage implements ModelServiceLocator {

@SpringBean private CounterManager counterManager;

@SpringBean private ClusterExecutionHelper clusterExecutionHelper;

private List<Breadcrumb> breadcrumbs;

private boolean initialized = false;
Expand Down Expand Up @@ -566,6 +569,9 @@ public AuditService getAuditService() {
return auditService;
}

public ClusterExecutionHelper getClusterExecutionHelper() {
return clusterExecutionHelper;
}

public AccessCertificationService getCertificationService() {
return certficationService;
Expand Down
Expand Up @@ -48,6 +48,7 @@ public class SelectableBean<T extends Serializable> extends Selectable<T> implem

//TODO probably this should not be here. find better place if needed, e.g. subclass with specific behaviour and attributes.
private int activeSessions;
private List<String> nodes;

/**
* Result of object retrieval (or attempt of object retrieval). It case that it is not error the result is optional.
Expand Down Expand Up @@ -91,6 +92,14 @@ public int getActiveSessions() {
return activeSessions;
}

public List<String> getNodes() {
return nodes;
}

public void setNodes(List<String> nodes) {
this.nodes = nodes;
}

public List<InlineMenuItem> getMenuItems() {
if (menuItems == null) {
menuItems = new ArrayList<>();
Expand Down
Expand Up @@ -15,18 +15,23 @@
*/
package com.evolveum.midpoint.web.page.admin.configuration;

import com.evolveum.midpoint.CacheInvalidationContext;
import com.evolveum.midpoint.TerminateSessionEvent;
import com.evolveum.midpoint.gui.api.GuiStyleConstants;
import com.evolveum.midpoint.gui.api.component.BasePanel;
import com.evolveum.midpoint.gui.api.component.MainObjectListPanel;
import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.model.api.authentication.MidPointUserProfilePrincipal;
import com.evolveum.midpoint.model.api.authentication.UserProfileService;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.web.component.data.BaseSortableDataProvider;
import com.evolveum.midpoint.web.component.data.column.ColumnMenuAction;
import com.evolveum.midpoint.web.component.menu.cog.ButtonInlineMenuItem;
import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem;
import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItemAction;
import com.evolveum.midpoint.web.component.util.ListDataProvider2;
import com.evolveum.midpoint.web.component.util.SelectableBean;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.UserSessionManagementListType;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.UserSessionManagementType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import org.apache.commons.collections4.CollectionUtils;
Expand All @@ -35,15 +40,22 @@
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;

import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.evolveum.midpoint.model.common.expression.functions.BasicExpressionFunctions.LOGGER;

public class InternalsLoggedInUsersPanel<F extends FocusType> extends BasePanel<F> {

private static final String ID_TABLE = "table";

private static final String DOT_CLASS = InternalsLoggedInUsersPanel.class.getName() + ".";
private static final String OPERATION_LOAD_PRINCIPALS_REMOte_NODES = DOT_CLASS + "loadPrincipalsFromRemoteNodes";

public InternalsLoggedInUsersPanel(String id) {
super(id);
}
Expand Down Expand Up @@ -74,28 +86,21 @@ protected List<InlineMenuItem> createInlineMenu() {

@Override
protected BaseSortableDataProvider<SelectableBean<F>> initProvider() {
// List<MidPointUserProfilePrincipal> principals = getPageBase().getModelInteractionService().getLoggedInUsers();
// List<SelectableBean<F>> users = new ArrayList<>(principals.size());
// for (MidPointUserProfilePrincipal principal : principals) {
// SelectableBean<F> user = new SelectableBean<F>((F) principal.getUser());
// user.setActiveSessions(principal.getActiveSessions());
// users.add(user);
// }

LoadableModel<List<MidPointUserProfilePrincipal>> principals = new LoadableModel<List<MidPointUserProfilePrincipal>>(true) {
LoadableModel<List<UserSessionManagementType>> principals = new LoadableModel<List<UserSessionManagementType>>(true) {

@Override
protected List<MidPointUserProfilePrincipal> load() {
return getPageBase().getModelInteractionService().getLoggedInUsers();
protected List<UserSessionManagementType> load() {
return loadLoggedIUsersFromAllNodes();
}
};

return new ListDataProvider2<SelectableBean<F>, MidPointUserProfilePrincipal>(InternalsLoggedInUsersPanel.this, principals) {
return new ListDataProvider2<SelectableBean<F>, UserSessionManagementType>(InternalsLoggedInUsersPanel.this, principals) {

@Override
protected SelectableBean<F> createObjectWrapper(MidPointUserProfilePrincipal principal) {
SelectableBean<F> user = new SelectableBean<>((F) principal.getUser());
protected SelectableBean<F> createObjectWrapper(UserSessionManagementType principal) {
SelectableBean<F> user = new SelectableBean<F>((F) principal.getUser());
user.setActiveSessions(principal.getActiveSessions());
user.setNodes(principal.getNode());
return user;
}
};
Expand All @@ -115,10 +120,55 @@ protected List<Component> createToolbarButtonsList(String buttonId) {
add(table);
}

private List<UserSessionManagementType> loadLoggedIUsersFromAllNodes() {
OperationResult result = new OperationResult(OPERATION_LOAD_PRINCIPALS_REMOte_NODES);

List<UserSessionManagementType> loggedUsers = getPageBase().getModelInteractionService().getLoggedInUsers();

Map<String, UserSessionManagementType> usersMap = loggedUsers.stream().collect(Collectors.toMap(key -> key.getUser().getOid(), value -> value));

getPageBase().getClusterExecutionHelper().execute((client, operationResult) -> {

client.path(UserProfileService.EVENT_LIST_USER_SESSION);
Response response = client.get();
LOGGER.info("Cluster-wide cache clearance finished with status {}, {}", response.getStatusInfo().getStatusCode(),
response.getStatusInfo().getReasonPhrase());

if (!response.hasEntity()) {
return;
}

UserSessionManagementListType sessionUsers = response.readEntity(UserSessionManagementListType.class);
response.close();

List<UserSessionManagementType> nodeSpecificSessions = sessionUsers.getSession();

if (sessionUsers == null || nodeSpecificSessions == null || nodeSpecificSessions.isEmpty()) {
return;
}

for (UserSessionManagementType user : nodeSpecificSessions) {
UserSessionManagementType existingUser = usersMap.get(user.getUser().getOid());
if (existingUser != null) {
existingUser.setActiveSessions(existingUser.getActiveSessions() + user.getActiveSessions());
existingUser.getNode().addAll(user.getNode());
continue;
}

usersMap.put(user.getUser().getOid(), user);
}

}, " list principals from remote nodes ", result);


return new ArrayList<>(usersMap.values());
}

private List<IColumn<SelectableBean<F>, String>> initColumns() {
List<IColumn<SelectableBean<F>, String>> columns = new ArrayList<>();
columns.add(new PropertyColumn<>(createStringResource("ActivationType.effectiveStatus"), "value.activation.effectiveStatus"));
columns.add(new PropertyColumn<>(createStringResource("InternalsLoggedInUsers.activeSessions"), "activeSessions"));
columns.add(new PropertyColumn<>(createStringResource("InternalsLoggedInUsers.nodes"), "nodes"));
return columns;
}

Expand Down Expand Up @@ -160,13 +210,19 @@ public boolean isHeaderMenuItem(){
private void expireSessionsFor(AjaxRequestTarget target, F selectedObject) {
List<String> selected = getSelectedObjects(selectedObject);
if (CollectionUtils.isEmpty(selected)) {
getSession().warn("InternalsLoggedInUsersPanel.expireSession.warn");
getSession().warn(getString("InternalsLoggedInUsersPanel.expireSession.warn"));
target.add(getPageBase().getFeedbackPanel());
return;
}

getPageBase().getModelInteractionService().expirePrincipals(selected);
getSession().success("InternalsLoggedInUsersPanel.expireSession.success");
TerminateSessionEvent details = new TerminateSessionEvent();
details.setPrincipalOids(selected);
CacheInvalidationContext ctx = new CacheInvalidationContext(false, details);
ctx.setTerminateSession(true);
getPageBase().getCacheDispatcher().dispatchInvalidation(null, null, true, ctx);

//getPageBase().getModelInteractionService().expirePrincipals(selected);
getSession().success(getString("InternalsLoggedInUsersPanel.expireSession.success"));
target.add(getPageBase().getFeedbackPanel());
}

Expand Down
@@ -0,0 +1,25 @@
package com.evolveum.midpoint.web.page.admin.configuration.dto;

import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;

import java.io.Serializable;
import java.util.List;

public class PrincipalDto implements Serializable {

private UserType userType;
private List<String> nodeIdentidier;

public PrincipalDto(UserType userType, List<String> nodeIdentidier) {
this.userType = userType;
this.nodeIdentidier = nodeIdentidier;
}

public List<String> getNodeIdentidier() {
return nodeIdentidier;
}

public void setNodeIdentidier(List<String> nodeIdentidier) {
this.nodeIdentidier = nodeIdentidier;
}
}
22 changes: 22 additions & 0 deletions infra/common/pom.xml
Expand Up @@ -120,6 +120,28 @@
<artifactId>javax.annotation-api</artifactId>
</dependency>

<!-- rest providers -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-extension-providers</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<scope>compile</scope>
</dependency>



<!-- Testing dependecies -->
<dependency>
<groupId>org.testng</groupId>
Expand Down
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.evolveum.midpoint.model.impl.rest;
package com.evolveum.midpoint.common.rest;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
Expand Down
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.evolveum.midpoint.model.impl.rest;
package com.evolveum.midpoint.common.rest;

import org.jetbrains.annotations.NotNull;

Expand Down
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.evolveum.midpoint.model.impl.rest;
package com.evolveum.midpoint.common.rest;

import java.io.IOException;
import java.io.InputStream;
Expand Down
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.evolveum.midpoint.model.impl.rest;
package com.evolveum.midpoint.common.rest;

import java.io.InputStream;

Expand Down
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.evolveum.midpoint.model.impl.rest;
package com.evolveum.midpoint.common.rest;

import java.io.InputStream;

Expand Down
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.evolveum.midpoint.model.impl.rest;
package com.evolveum.midpoint.common.rest;

import java.io.InputStream;

Expand Down

0 comments on commit b8b56dd

Please sign in to comment.