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 org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.portal.PortalContext; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.portal.wssynclibrary.shared.ItemNotSynched; import org.gcube.portal.wssynclibrary.shared.WorkspaceFolderLocked; import org.gcube.portal.wssynclibrary.shared.thredds.Sync_Status; 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.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; /** * 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; } } /** * Do sync folder. * * @param folderId the folder id * @param clientConfig the th config * @return the th sync status * @throws Exception the exception */ /* (non-Javadoc) * @see org.gcube.portlets.widgets.wsthreddssync.client.rpc.ThreddsWorkspaceSyncService#doSyncFolder(java.lang.String, org.gcube.portlets.widgets.wsthreddssync.shared.WsThreddsSynchFolderDescriptor) */ @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()); String targetScopeUserToken = null; ThSynchFolderConfiguration config = null; if(clientConfig!=null) { targetScopeUserToken = PortalContext.getConfiguration().getCurrentUserToken(clientConfig.getSelectedScope().getScopeName(), user.getUsername()); config = BeanConverter.toThSynchFolderConfiguration(clientConfig, folderId, targetScopeUserToken); logger.debug("Creating server config "+config); } logger.info("Calling doSyncFolder on folderId: "+folderId +", config: "+config); String wsScope = PortalContext.getConfiguration().getCurrentScope(this.getThreadLocalRequest()); String wsUserToken = PortalContext.getConfiguration().getCurrentUserToken(wsScope, user.getUsername()); ThSyncStatus status = getSyncService().doSyncFolder(folderId, config, wsScope, wsUserToken); 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, try again later"); } } /** * Gets the available THREDDS catalogues for target scope. * * @param targetFullScope the target scope * @return the available catalogues for scope * @throws Exception the exception */ @Override public List getAvailableCataloguesForScope(String targetFullScope) throws Exception { if(targetFullScope==null) throw new Exception("Invalid scope null"); String originalScope = null; String originalToken = null; List listCtlgs = null; try { GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); String wsScope = PortalContext.getConfiguration().getCurrentScope(this.getThreadLocalRequest()); String wsUserToken = PortalContext.getConfiguration().getCurrentUserToken(wsScope, user.getUsername()); //Thread Local contexts originalScope = wsScope; originalToken = wsUserToken; String targetScopeUserToken = PortalContext.getConfiguration().getCurrentUserToken(targetFullScope, user.getUsername()); listCtlgs = getSyncService().getAvailableCataloguesByToken(targetFullScope, wsUserToken, targetScopeUserToken); 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); }finally { if(originalScope!=null && originalScope.compareTo(targetFullScope)!=0) { logger.info("Resetting the scope: "+originalScope + " which was original WS context"); ScopeProvider.instance.set(originalScope); if(originalToken!=null) { logger.info("Resetting the user token: "+originalToken.substring(0,10)+"-MASKED-TOKEN which was original WS context"); SecurityTokenProvider.instance.set(originalToken); } } } return listCtlgs; } /** * 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"); GCubeUser user = null; Map mapScopesRoles = null; //DEV MODE if (!isWithinPortal()){ mapScopesRoles = new HashMap(); mapScopesRoles.put("/gcube/devNext/NextNext", GatewayRolesThredds.DATA_MANAGER); // mapScopesRoles.put( "/gcube", GatewayRolesThredds.THREDDS_PUBLISHER); // mapScopesRoles.put( "/gcube/devNext/NextNext", GatewayRolesThredds.THREDDS_PUBLISHER); return mapScopesRoles; } try { user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); mapScopesRoles = WsUtil.getScopesWithThreddsRolesForUser(user); 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("getListOfVREsForLoggedUser...: "); GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); long userId = user.getUserId(); // Instanciate 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); } //ADDING THE ROOT SCOPE /*String infraName = PortalContext.getConfiguration().getInfrastructureName(); GcubeScope gcubeRoot = new GcubeScope(infraName, "/"+infraName, GcubeScopeType.ROOT); listOfScopes.add(gcubeRoot)*/ } 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; } /** * Checks if is item synched. * * @param folderId the folder id * @return the ws thredds synch folder descriptor * @throws WorkspaceFolderLocked the workspace folder locked * @throws Exception the exception */ /* (non-Javadoc) * @see org.gcube.portlets.widgets.wsthreddssync.client.rpc.ThreddsWorkspaceSyncService#isItemSynched(java.lang.String) */ @Override public WsThreddsSynchFolderDescriptor isItemSynched(String folderId) throws WorkspaceFolderLocked, Exception{ logger.debug("Performing isItemSynched for foldeId: "+folderId); try { GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); String wsScope = PortalContext.getConfiguration().getCurrentScope(this.getThreadLocalRequest()); Sync_Status theStatus = getSyncService().getSynchedStatusFromItemProperty(folderId, wsScope, user.getUsername()); if(theStatus!=null) { logger.info("Folder id: "+folderId+" is synched"); String wsUserToken = PortalContext.getConfiguration().getCurrentUserToken(wsScope, user.getUsername()); ThSyncFolderDescriptor serverFolderSync = getSyncService().checkItemSynched(folderId,wsScope,wsUserToken); WsThreddsSynchFolderDescriptor toWsThreddFolder = BeanConverter.toWsThreddsFolderConfig(serverFolderSync, theStatus); 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 FolderDescriptor"); 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); } } /** * Register callback for id. * * @param folderId the folder id * @throws Exception the exception */ public void registerCallbackForId(String folderId) throws Exception{ GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); String wsScope = PortalContext.getConfiguration().getCurrentScope(this.getThreadLocalRequest()); String wsUserToken = PortalContext.getConfiguration().getCurrentUserToken(wsScope, user.getUsername()); getSyncService().registerCallbackForId(folderId, wsScope, wsUserToken); } /** * Monitor sync status. * * @param folderId the folder id * @return the th sync status * @throws ItemNotSynched the item not synched * @throws Exception the exception */ /* (non-Javadoc) * @see org.gcube.portlets.widgets.wsthreddssync.client.rpc.ThreddsWorkspaceSyncService#monitorSyncStatus(java.lang.String) */ @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); } /** * Do sync folder. * * @param folderId the folder id * @return the th sync status * @throws Exception the exception */ /* (non-Javadoc) * @see org.gcube.portlets.widgets.wsthreddssync.client.rpc.ThreddsWorkspaceSyncService#doSyncFolder(java.lang.String, org.gcube.portlets.widgets.wsthreddssync.shared.WsThreddsSynchFolderDescriptor) */ @Override public Boolean doUnSyncFolder(final String folderId) throws Exception{ logger.info("Performing unsync on folder id: "+folderId); // String scope = PortalContext.getConfiguration().getCurrentScope(this.getThreadLocalRequest()); // GCubeUser username = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); // String groupName = PortalContext.getConfiguration().getCurrentGroupName(this.getThreadLocalRequest()); // new GcubeVRE(groupName, scope) try { GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest()); String wsScope = PortalContext.getConfiguration().getCurrentScope(this.getThreadLocalRequest()); String wsUserToken = PortalContext.getConfiguration().getCurrentUserToken(wsScope, user.getUsername()); return getSyncService().doUnSync(folderId, false, wsScope, wsUserToken); }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"); } } }