Task #10000, Enable remove account option in Gateways

git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/admin/remove-account-portlet@182064 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Massimiliano Assante 2019-10-17 15:31:42 +00:00
parent c01008b7f9
commit 6be37244c7
10 changed files with 284 additions and 27 deletions

View File

@ -15,6 +15,7 @@
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">

View File

@ -1,8 +1,2 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.8

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="RemoveAccount-portlet">
<wb-module deploy-name="remove-account-portlet">
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>

20
pom.xml
View File

@ -1,6 +1,7 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@ -13,7 +14,7 @@
<artifactId>remove-account-portlet</artifactId>
<packaging>war</packaging>
<name>RemoveAccount Portlet</name>
<version>1.0.0-SNAPSHOT</version>
<version>1.1.0-SNAPSHOT</version>
<description>
remove-account-portlet is a component that install in the contro panel userr account as a tab and permits the user to remvoe his or her account
</description>
@ -52,6 +53,19 @@
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.gcube.resources.discovery</groupId>
<artifactId>ic-client</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>storagehub-client-library</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-encryption</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.dvos</groupId>
<artifactId>usermanagement-core</artifactId>
@ -143,7 +157,7 @@
<pluginType>portlet</pluginType>
</configuration>
</plugin>
<plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>

View File

@ -7,6 +7,8 @@ import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.ProcessAction;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.model.User;
import com.liferay.portal.theme.ThemeDisplay;
@ -17,26 +19,33 @@ import com.liferay.util.bridges.mvc.MVCPortlet;
* Portlet implementation class RemoveAccountPortlet
*/
public class RemoveAccountPortlet extends MVCPortlet {
private static Log _log = LogFactoryUtil.getLog(RemoveAccountPortlet.class);
public static final String AUTORISED_INFRA_ROLE = "Infrastructure-Manager";
@ProcessAction(name = "deleteAccount")
public void deleteAccount(ActionRequest actionRequest,
ActionResponse response) throws IOException, PortletException {
public void deleteAccount(ActionRequest actionRequest, ActionResponse response) throws IOException, PortletException {
User user = null;
try {
user = PortalUtil.getUser(actionRequest);
} catch (Exception e) {
e.printStackTrace();
}
}
String username2Remove = user.getScreenName();
_log.info("Trying to remove user from LDAP ...");
Thread removeFromLDAPThread = new Thread(new RemovedUserFromLDAPThread(username2Remove));
removeFromLDAPThread.start();
_log.info("Trying to remove user from Liferay DB and JCR and notify infra-managers ...");
Thread emailManagersThread = new Thread(new RemovedUserAccountThread(
user.getUserId(),
user.getScreenName(),
username2Remove,
user.getFullName(),
user.getEmailAddress()));
emailManagersThread.start();
ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
response.sendRedirect(themeDisplay.getURLSignOut());
}
}

View File

@ -0,0 +1,74 @@
package org.gcube.portlets.admin;
import static org.gcube.common.authorization.client.Constants.authorizationService;
import java.util.ArrayList;
import java.util.List;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.portal.PortalContext;
import org.gcube.common.storagehub.client.plugins.AbstractPlugin;
import org.gcube.common.storagehub.client.proxies.UserManagerClient;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.gcube.vomanagement.usermanagement.RoleManager;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.impl.LiferayRoleManager;
import org.gcube.vomanagement.usermanagement.model.GCubeRole;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
/**
*
* @author Massimiliano Assante ISTI-CNR
*
*/
public class RemoveUserFromJCR {
private static Log _log = LogFactoryUtil.getLog(RemoveUserFromJCR.class);
private String username2Delete;
private GroupManager gm;
private UserManager uMan;
public RemoveUserFromJCR(String username2Delete, GroupManager gm, UserManager uMan) {
this.username2Delete = username2Delete;
this.gm = gm;
this.uMan = uMan;
}
public boolean remove() {
try {
//get the super user
String infraContext = "/"+PortalContext.getConfiguration().getInfrastructureName();
long groupId = gm.getGroupIdFromInfrastructureScope(infraContext);
RoleManager rm = new LiferayRoleManager();
long roleId = rm.getRoleId(RemoveAccountPortlet.AUTORISED_INFRA_ROLE, groupId);
List<GCubeUser> users = uMan.listUsersByGroupAndRole(groupId, roleId);
if (users.isEmpty()) {
_log.error("Cannot delete the user: there is no user having role " + RemoveAccountPortlet.AUTORISED_INFRA_ROLE + " on context: " + infraContext);
return false;
}
else {
GCubeUser theAdmin = users.get(0);
String adminUsername = theAdmin.getUsername();
String theAdminToken = PortalContext.getConfiguration().getCurrentUserToken(infraContext, adminUsername);
List<GCubeRole> theAdminRoles = rm.listRolesByUserAndGroup(theAdmin.getUserId(), groupId);
List<String> rolesString = new ArrayList<String>();
for (GCubeRole gCubeRole : theAdminRoles) {
rolesString.add(gCubeRole.getRoleName());
}
authorizationService().setTokenRoles(theAdminToken, rolesString);
SecurityTokenProvider.instance.set(theAdminToken);
UserManagerClient userClient = AbstractPlugin.users().build();
userClient.removeUser(username2Delete);
return true;
}
} catch (Exception e) {
_log.error("Could not delete " + username2Delete + " from JCR ", e);
return false;
}
}
}

View File

@ -33,6 +33,8 @@ public class RemovedUserAccountThread implements Runnable {
private String fullName;
private String emailAddress;
private long userId;
private GroupManager gm;
private UserManager uMan;
public RemovedUserAccountThread(long userId,String userName, String fullName, String emailAddress) {
super();
@ -40,25 +42,35 @@ public class RemovedUserAccountThread implements Runnable {
this.userName = userName;
this.fullName = fullName;
this.emailAddress = emailAddress;
this.uMan = new LiferayUserManager();
this.gm = new LiferayGroupManager();
}
@Override
public void run() {
try {
_log.info("Trying to remove user " + userName + " from JCR first, using storageHub with role: "+RemoveAccountPortlet.AUTORISED_INFRA_ROLE);
RemoveUserFromJCR rmJCR = new RemoveUserFromJCR(userName, gm, uMan);
boolean result = rmJCR.remove();
_log.info("The user " + userName + " has been removed from JCR with success? " + result);
} catch (Exception e) {
_log.error("An error occurred during user workspace removal: ", e);
}
handleUserRemoval(userId, userName, fullName, emailAddress);
}
private void handleUserRemoval(long userId, String userName, String fullName, String emailAddress) {
System.out.println("trying removeUser account for " + userName);
_log.info("trying removeUser account for " + userName);
//first remove the account
try {
UserLocalServiceUtil.deleteUser(userId);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("removeUser account for " + userName + " done with success, now notify the managers ... ");
_log.info("removeUser account for " + userName + " done with success, now notify the managers ... ");
//the notify the managers
UserManager um = new LiferayUserManager();
GroupManager gm = new LiferayGroupManager();
RoleManager rm = new LiferayRoleManager();
try {
String rootVoName = PortalContext.getConfiguration().getInfrastructureName();
@ -73,7 +85,7 @@ public class RemovedUserAccountThread implements Runnable {
}
_log.trace("Root is: " + rootVoName + " Scanning roles ....");
List<GCubeUser> managers = um.listUsersByGroupAndRole(groupId, infraManagerRoleId);
List<GCubeUser> managers = uMan.listUsersByGroupAndRole(groupId, infraManagerRoleId);
if (managers == null || managers.isEmpty()) {
_log.warn("There are no users with (Site) Role " + infraManagerRoleId + " on " + rootVoName + " in this portal. Will not notify about removed user accounts.");
}

View File

@ -0,0 +1,153 @@
package org.gcube.portlets.admin;
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.util.List;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import org.gcube.common.encryption.encrypter.StringEncrypter;
import org.gcube.common.portal.PortalContext;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.Property;
import org.gcube.common.resources.gcore.utils.Group;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
/**
*
* @author Massimiliano Assante ISTI-CNR
*
*/
public class RemovedUserFromLDAPThread implements Runnable {
private static Log _log = LogFactoryUtil.getLog(RemovedUserFromLDAPThread.class);
private static final String LDAP_SERVER_NAME = "LDAPServer";
private static final String LDAP_SERVER_FILTER_NAME = "filter";
private static final String LDAP_SERVER_PRINCPAL_NAME = "ldapPrincipal";
private static final String USER_CONTEXT = ",ou=People,o=D4Science,ou=Organizations,dc=d4science,dc=org";
private String portalName;
private String ldapUrl;
private String principal;
private String ldapPassword;
private String username2Delete;
public RemovedUserFromLDAPThread(String username2Delete) {
this.username2Delete = username2Delete;
}
@SuppressWarnings("deprecation")
@Override
public void run() {
portalName = PortalContext.getPortalInstanceName();
PortalContext context = PortalContext.getConfiguration();
String scope = "/" + context.getInfrastructureName();
ScopeProvider.instance.set(scope);
SimpleQuery query = queryFor(ServiceEndpoint.class);
query.addCondition("$resource/Profile/Category/text() eq 'Portal'");
query.addCondition("$resource/Profile/Name/text() eq '" + portalName + "'");
DiscoveryClient<ServiceEndpoint> client = clientFor(ServiceEndpoint.class);
List<ServiceEndpoint> list = client.submit(query);
if (list == null || list.isEmpty()) {
_log.error("Could not find any Service endpoint registred in the infrastructure for this portal: " + portalName);
}
else if (list.size() > 1) {
_log.warn("Found more than one Service endpoint registred in the infrastructure for this portal: " + portalName);
}
else {
for (ServiceEndpoint res : list) {
Group<AccessPoint> apGroup = res.profile().accessPoints();
AccessPoint[] accessPoints = (AccessPoint[]) apGroup.toArray(new AccessPoint[apGroup.size()]);
for (int i = 0; i < accessPoints.length; i++) {
if (accessPoints[i].name().compareTo(LDAP_SERVER_NAME) == 0) {
_log.info("Found credentials for " + LDAP_SERVER_NAME);
AccessPoint found = accessPoints[i];
ldapUrl = found.address();
String encrPassword = found.password();
try {
ldapPassword = StringEncrypter.getEncrypter().decrypt( encrPassword);
} catch (Exception e) {
_log.error("Something went wrong while decrypting password for " + LDAP_SERVER_NAME);
e.printStackTrace();
}
Group<Property> propGroup = found.properties();
Property[] props = (Property[]) propGroup.toArray(new Property[propGroup.size()]);
for (int j = 0; j < props.length; j++) {
if (props[j].name().compareTo(LDAP_SERVER_PRINCPAL_NAME) == 0) {
_log.info("\tFound properties of " + LDAP_SERVER_PRINCPAL_NAME);
String encrValue = props[j].value();
try {
principal = StringEncrypter.getEncrypter().decrypt(encrValue);
} catch (Exception e) {
_log.error("Something went wrong while decrypting value for " + LDAP_SERVER_PRINCPAL_NAME);
e.printStackTrace();
}
}
}
}
}
}
_log.debug("Got LDAP connection info from IS Resource ...");
/*************** */
_log.debug("Initializing LDAP connection ...");
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_PRINCIPAL, principal);
env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
try {
Context ctx = new InitialContext(env);
String userCtx2Delete = getSubContext(username2Delete);
// Remove the binding
_log.debug("***** trying delete userCtx=" + userCtx2Delete);
ctx.unbind(userCtx2Delete);
// Check that it is gone
Object obj = null;
try {
obj = ctx.lookup(userCtx2Delete);
} catch (NameNotFoundException ne) {
_log.info("unbind successful for "+userCtx2Delete);
return;
}
_log.error("unbind failed; object still there: " + obj);
// Close the context when we're done
ctx.close();
} catch (NamingException e) {
_log.error("Something went Wrong during LDAP remove user");
e.printStackTrace();
} catch (Exception es) {
_log.error("Something went Wrong during LDAP remove user in retrieving Liferay Organization");
es.printStackTrace();
}
}
}
/**
*
* @param username
* @return the single user subContext
*/
private String getSubContext(String username) {
return "uid="+username+USER_CONTEXT;
}
}

View File

@ -1,9 +1,9 @@
name=RemoveAccount
module-group-id=liferay
module-incremental-version=1
module-incremental-version=2
tags=
short-description=
change-log=
page-url=http://www.gcube-system.org
author=M. Assante
licenses=EUPL
licenses=EUPL

View File

@ -7,9 +7,9 @@
<h3>Delete your Account</h3>
<p>Deleting your account will disable your profile and remove your
name and photo from most things you've shared on this <a href="http://www.d4science.org/" target="_blank">D4Science</a> gateway.</p>
name and photo you've shared on this <a href="http://www.d4science.org/" target="_blank">D4Science</a> gateway.</p>
<p>Some information may still be visible to others, such as your
name in the posts and private messages you sent. Non shared files and folders of your virtual workspace will be removed.</p>
name in the posts and private messages you sent. All files and folders you created of your workspace will be removed.</p>
<div class="alert alert-block">
<h4>Warning</h4>