package org.gcube.portlets.widgets.wsthreddssync.server; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import org.gcube.common.portal.PortalContext; import org.gcube.portal.wssynclibrary.shared.ItemNotSynched; import org.gcube.portal.wssynclibrary.shared.WorkspaceFolderLocked; import org.gcube.portal.wssynclibrary.shared.thredds.ThCatalogueBean; import org.gcube.portal.wssynclibrary.shared.thredds.ThSyncFolderDescriptor; import org.gcube.portal.wssynclibrary.shared.thredds.ThSyncStatus; import org.gcube.portal.wssynclibrary.shared.thredds.ThSynchFolderConfiguration; import org.gcube.portlets.widgets.wsthreddssync.client.rpc.ThreddsWorkspaceSyncService; import org.gcube.portlets.widgets.wsthreddssync.shared.GatewayRolesThredds; import org.gcube.portlets.widgets.wsthreddssync.shared.GcubeScope; import org.gcube.portlets.widgets.wsthreddssync.shared.GcubeScopeType; import org.gcube.portlets.widgets.wsthreddssync.shared.WsThreddsSynchFolderConfiguration; import org.gcube.portlets.widgets.wsthreddssync.shared.WsThreddsSynchFolderDescriptor; import org.gcube.usecases.ws.thredds.SyncEngine; import org.gcube.vomanagement.usermanagement.GroupManager; import org.gcube.vomanagement.usermanagement.exception.GroupRetrievalFault; import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException; import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault; import org.gcube.vomanagement.usermanagement.impl.LiferayGroupManager; import org.gcube.vomanagement.usermanagement.model.GCubeGroup; import org.gcube.vomanagement.usermanagement.model.GCubeUser; import org.gcube.vomanagement.usermanagement.model.GatewayRolesNames; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.liferay.portal.service.UserLocalServiceUtil; // TODO: Auto-generated Javadoc /** * The server side implementation of the RPC service. * * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Feb 14, 2018 */ @SuppressWarnings("serial") public class ThreddsWorkspaceSyncServiceImpl extends RemoteServiceServlet implements ThreddsWorkspaceSyncService { /** The logger. */ private static Logger logger = LoggerFactory.getLogger(ThreddsWorkspaceSyncServiceImpl.class); /** The sync thredds. */ private SyncronizeWithThredds syncThredds = null; /** * Gets the sync service. * * @return the sync service */ public synchronized SyncronizeWithThredds getSyncService() { if (syncThredds == null) syncThredds = new SyncronizeWithThredds(); return syncThredds; } /** * Checks if is within portal. * * @return true if you're running into the portal, false if in development */ public static boolean isWithinPortal() { try { UserLocalServiceUtil.getService(); return true; } catch (Exception ex) { logger.warn("Development Mode ON"); return false; } } /** * Gets the available THREDDS catalogues for target scope. * * @param targetFullScope the target scope * @return the available catalogues for scope * @throws Exception the exception */ // UPDATED @Override public List getAvailableCataloguesForScope(String targetFullScope) throws Exception { if (targetFullScope == null) throw new Exception("Invalid scope null"); List listCtlgs = null; try { GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); listCtlgs = getSyncService().getAvailableCatalogues(this.getThreadLocalRequest(), user, targetFullScope); logger.debug("Retuning " + listCtlgs.size() + " Catalogues for scope: " + targetFullScope); if (logger.isDebugEnabled()) { for (ThCatalogueBean thCatalogueBean : listCtlgs) { logger.debug(thCatalogueBean.toString()); } } } catch (Exception e) { logger.error("Error on checking available Catalogue in the scope: " + targetFullScope, e); } return listCtlgs; } /** * Gets the configuration. * * @param folderId the folder id * @param loadStatus the load status. If true it loads the status by calling the * {@link SyncEngine#check(String, boolean)} but it is time * consuming. No otherwise. * @return the ws thredds synch folder descriptor * @throws WorkspaceFolderLocked the workspace folder locked * @throws Exception the exception */ @Override public WsThreddsSynchFolderDescriptor getConfiguration(String folderId, boolean loadStatus) throws WorkspaceFolderLocked, Exception { logger.debug("called isItemSynched for folderId: " + folderId); GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); return getConfiguration(folderId, loadStatus, this.getThreadLocalRequest(), user); } /** * Gets the configuration. * * @param folderId the folder id * @param loadStatus the load status * @param httpRequest the http request * @param user the user * @return the configuration * @throws Exception the exception */ public WsThreddsSynchFolderDescriptor getConfiguration(String folderId, boolean loadStatus, HttpServletRequest httpRequest, GCubeUser user) throws Exception { logger.debug("called internal getConfiguration for folderId: " + folderId); try { ThSyncFolderDescriptor theConfig = getSyncService().getConfiguration(folderId, loadStatus, httpRequest, user); if (theConfig != null) { logger.info("Folder id: " + folderId + " is synched"); WsThreddsSynchFolderDescriptor toWsThreddFolder = BeanConverter.toWsThreddsFolderConfig(theConfig); logger.debug("isItemSynched for id: " + folderId + " returning: " + toWsThreddFolder); return toWsThreddFolder; } logger.info("Folder id: " + folderId + " is not synched, returning null descriptor"); return null; } catch (ItemNotSynched e) { logger.info("The folderId: " + folderId + " is not synched, returning null for " + WsThreddsSynchFolderDescriptor.class.getSimpleName()); return null; } catch (WorkspaceFolderLocked e) { logger.warn(e.getMessage() + ", sending exception to client..."); throw new WorkspaceFolderLocked(e.getFolderId(), e.getMessage()); } catch (Exception e) { logger.info("Error on isItemSynched for folderId: " + folderId, e); throw new Exception(e); } } /** * Do sync folder. * * @param folderId the folder id * @param clientConfig the client config * @return the th sync status * @throws Exception the exception */ // UPDATED @Override public ThSyncStatus doSyncFolder(final String folderId, WsThreddsSynchFolderConfiguration clientConfig) throws Exception { logger.info("Performing doSyncFolder method on id: " + folderId + ", config: " + clientConfig); try { GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); ThSynchFolderConfiguration config = null; if (clientConfig != null && clientConfig.getSelectedScope() != null) { config = BeanConverter.toThSynchFolderConfiguration(clientConfig, folderId, clientConfig.getSelectedScope().getScopeName()); logger.debug("Creating server config " + config); } else { logger.info("The config sent from client is null, Loading it from ws-thredds"); ThSyncFolderDescriptor descr = getSyncService().getConfiguration(folderId, false, this.getThreadLocalRequest(), user); logger.info("From ws-thredds loaded the config: " + config); config = descr.getConfiguration(); } ThSyncStatus status = getSyncService().doSyncFolder(folderId, config, this.getThreadLocalRequest(), user); logger.debug("Returning for folderId " + folderId + " the syncStatus: " + status); return status; } catch (Exception e) { logger.error("Do sync Folder error: ", e); throw new Exception( "Sorry, an error occurred during synchonization phase. The server encountered the error: " + e.getMessage(), e); } } /** * Do un sync folder. * * @param folderId the folder id * @return the boolean * @throws Exception the exception */ // Updated @Override public Boolean doUnSyncFolder(final String folderId) throws Exception { logger.info("Performing unsync on folder id: " + folderId); try { GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); ThSyncFolderDescriptor foldeDesr = getSyncService().getConfiguration(folderId, false, this.getThreadLocalRequest(), user); return getSyncService().doUnSync(folderId, true, foldeDesr.getConfiguration(), this.getThreadLocalRequest(), user); } catch (Exception e) { logger.error("Do un sync Folder error: ", e); throw new Exception( "Sorry, an error occurred on deleting sync configurations, refresh and try again later"); } } /** * Gets the list of Scopes (Root-VO, VOs and VREs) for user and the Thredds * roles that user has in them. * * @return the VREs and Thredds roles for a given user * @throws Exception the exception */ @Override public Map getScopesWithThreddsRolesForLoggedUser() throws Exception { logger.info("called getScopesWithThreddsRolesForLoggedUser"); Map mapScopesRoles = null; // DEV MODE if (!isWithinPortal()) { mapScopesRoles = new HashMap(); mapScopesRoles.put("/gcube/devsec/devVRE", GatewayRolesThredds.DATA_EDITOR); // mapScopesRoles.put( "/gcube", GatewayRolesThredds.THREDDS_PUBLISHER); // mapScopesRoles.put( "/gcube/devNext/NextNext", GatewayRolesThredds.THREDDS_PUBLISHER); return mapScopesRoles; } GCubeUser user = null; try { user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); String gatewayHostname = GenericUtils.getGatewayClientHostname(this.getThreadLocalRequest()); mapScopesRoles = WsUtil.getScopesWithThreddsRolesForUser(user, gatewayHostname); logger.info("returning Map(scopes,roles): " + mapScopesRoles); return mapScopesRoles; } catch (Exception e) { String errorMsg = "An error occurred on checking user roles. Refresh the page and try again."; logger.error("An error occurred on checking user roles for user: " + user, e); throw new Exception(errorMsg); } } /** * Gets the list scope with the role Data-Manager for logged user. * * @return the list of manager scopes for logged user * @throws Exception the exception */ @Override public List getListOfDataManagerScopesForLoggedUser() throws Exception { logger.info("called getListOfVREsForLoggedUser...: "); GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); long userId = user.getUserId(); // Instantiate the manager GroupManager groupManager = new LiferayGroupManager(); List listOfScopes = new ArrayList(); // DEV MODE if (!isWithinPortal()) { listOfScopes.add(new GcubeScope("devVRE", "/gcube/devsec/devVRE", GcubeScopeType.VRE)); listOfScopes.add(new GcubeScope("NextNext", "/gcube/devNext/NextNext", GcubeScopeType.VRE)); listOfScopes.add(new GcubeScope("devNext", "/gcube/devNext", GcubeScopeType.VO)); listOfScopes.add(new GcubeScope("devsec", "/gcube/devsec", GcubeScopeType.VO)); listOfScopes.add(new GcubeScope("gcube", "/gcube", GcubeScopeType.ROOT)); Collections.sort(listOfScopes); return listOfScopes; } try { String gatewayHostname = GenericUtils.getGatewayClientHostname(getThreadLocalRequest()); // list of Scopes filtered for gateway Set filteredGroupsForGatw = groupManager.listGroupsByUserAndSite(userId, gatewayHostname); // List listOfGroups = groupManager.listGroupsByUser(userId); List listOfGroups = new ArrayList(filteredGroupsForGatw); logger.info("list of VREs in the gateway " + gatewayHostname + " are " + listOfGroups.size()); for (GCubeGroup gCubeGroup : listOfGroups) { long groupId = gCubeGroup.getGroupId(); String fullScope = groupManager.getInfrastructureScope(groupId); logger.debug("For groupId: " + groupId + " got full scope: " + fullScope); GcubeScopeType scopeType = null; if (groupManager.isVRE(groupId)) { scopeType = GcubeScopeType.VRE; } else if (groupManager.isVO(groupId)) { scopeType = GcubeScopeType.VO; } // }else if(groupManager.isRootVO(gCubeGroup.getGroupId())){ // scopeType = GcubeScopeType.ROOT; // } if (scopeType != null) { GatewayRolesThredds roles = WsUtil.getThreddsRoleFor(user, gCubeGroup); // Adding only the scope where the user has the THREDDS_ADMIN role GcubeScope gcubeScope = checkDataManagerCapacityAndThreddsCatalogue(roles, gCubeGroup.getGroupName(), fullScope, groupManager, scopeType); if (gcubeScope != null) { listOfScopes.add(gcubeScope); } } } GCubeGroup theRootVO = groupManager.getRootVO(); GatewayRolesThredds roles = WsUtil.getThreddsRoleFor(user, theRootVO); String rootVOFullScope = groupManager.getInfrastructureScope(theRootVO.getGroupId()); /// ADDING THE ROOT SCOPE if the user has the THREDDS_ADMIN role in the ROOT-VO GcubeScope gcubeScope = checkDataManagerCapacityAndThreddsCatalogue(roles, theRootVO.getGroupName(), rootVOFullScope, groupManager, GcubeScopeType.ROOT); if (gcubeScope != null) { listOfScopes.add(gcubeScope); } } catch (UserRetrievalFault | UserManagementSystemException | GroupRetrievalFault e) { logger.error("Error occurred server-side getting VRE folders: ", e); throw new Exception("Sorry, an error occurred server-side getting VRE folders, try again later"); } if (listOfScopes.isEmpty()) { throw new Exception( "No scope detected with the needed role: " + GatewayRolesThredds.DATA_MANAGER.getRoleName() + ". Contact the VRE manager or the portal administrator"); } Collections.sort(listOfScopes); logger.info("Returning list of allowed scope/s with: " + GatewayRolesThredds.DATA_MANAGER + " role/s: " + listOfScopes); return listOfScopes; } /** * Checks if for the input scope: - the user has the role * {@link GatewayRolesThredds.#THREDDS_ADMIN} - the scope has an available * THREDDS catalogue configured * * @param role the role * @param scopeName the scope name e.g. devVRE * @param fullScope the full scope e.g. /gcube/devsec/devVRE * @param groupManager the group manager * @param scopeType the scope type * @return the gcube scope {@link GcubeScope} if the two conditions (see * description) are satisfied, null otherwise * @throws Exception the exception */ private GcubeScope checkDataManagerCapacityAndThreddsCatalogue(GatewayRolesThredds role, String scopeName, String fullScope, GroupManager groupManager, GcubeScopeType scopeType) throws Exception { logger.debug("checking Data-Manager capacity and THREEDS catalogues for role: " + role, "scope name: " + scopeName + ", scope: " + fullScope + " scope type: " + scopeType); if (role != null && role.getRoleName().equalsIgnoreCase(GatewayRolesNames.DATA_MANAGER.getRoleName())) { try { List list = getAvailableCataloguesForScope(fullScope); if (list != null) { return new GcubeScope(scopeName, fullScope, scopeType); } } catch (Exception e) { logger.error("Error on checking available catalogue for scope: " + fullScope, e); } } return null; } /** * Monitor sync status. * * @param folderId the folder id * @return the th sync status * @throws ItemNotSynched the item not synched * @throws Exception the exception */ @Override public ThSyncStatus monitorSyncStatus(String folderId) throws ItemNotSynched, Exception { GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); String wsScope = PortalContext.getConfiguration().getCurrentScope(this.getThreadLocalRequest()); String wsUserToken = PortalContext.getConfiguration().getCurrentUserToken(wsScope, user.getUsername()); return getSyncService().monitorSyncStatus(folderId, wsScope, wsUserToken); } }