package com.eas.server.handlers; import com.eas.client.RemoteServerModulesProxy; import com.eas.server.RequestHandler; import com.eas.client.cache.ScriptDocument; import com.eas.client.login.AnonymousPlatypusPrincipal; import com.eas.client.login.PlatypusPrincipal; import com.eas.client.threetier.requests.ServerModuleStructureRequest; import com.eas.script.Scripts; import com.eas.server.*; import com.eas.util.JsonUtils; import java.io.File; import java.security.AccessControlException; import java.util.Collections; import java.util.Date; import java.util.Set; import java.util.function.Consumer; import javax.security.auth.AuthPermission; /** * * @author pk, mg, ab */ public class ServerModuleStructureRequestHandler extends RequestHandler<ServerModuleStructureRequest, ServerModuleStructureRequest.Response> { public ServerModuleStructureRequestHandler(PlatypusServerCore aServerCore, ServerModuleStructureRequest aRequest) { super(aServerCore, aRequest); } @Override public void handle(Session aSession, Consumer<ServerModuleStructureRequest.Response> onSuccess, Consumer<Exception> onFailure) { String moduleName = getRequest().getModuleName(); if (moduleName == null || moduleName.isEmpty()) { onFailure.accept(new Exception("Module name is missing. Unnamed server modules are not allowed.")); } else { Date clientModuleTime = getRequest().getTimeStamp(); try { File file = serverCore.getIndexer().nameToFile(moduleName); ScriptDocument.ModuleDocument moduleDoc = serverCore.lookupModuleDocument(moduleName); if (file != null && moduleDoc != null) { ServerModuleStructureRequest.Response response = new ServerModuleStructureRequest.Response(null); Date serverModuleTime = new Date(file.lastModified()); if (clientModuleTime == null || serverModuleTime.after(clientModuleTime)) { checkPrincipalPermission(moduleDoc.getAllowedRoles(), moduleName); StringBuilder json = JsonUtils.o(RemoteServerModulesProxy.CREATE_MODULE_RESPONSE_FUNCTIONS_PROP, JsonUtils.as(moduleDoc.getFunctionProperties().toArray(new String[]{})).toString(), RemoteServerModulesProxy.CREATE_MODULE_RESPONSE_IS_PERMITTED_PROP, String.valueOf(true) ); response.setInfoJson(json.toString()); response.setTimeStamp(serverModuleTime); } onSuccess.accept(response); } else { onFailure.accept(new IllegalArgumentException(String.format("No module %s, or it is not a module", moduleName))); } } catch (AccessControlException ex) { if (ex.getPermission() instanceof AuthPermission) { onFailure.accept(ex); } else { StringBuilder json = JsonUtils.o(RemoteServerModulesProxy.CREATE_MODULE_RESPONSE_FUNCTIONS_PROP, JsonUtils.a(Collections.emptySet().toArray(new String[]{})).toString(), RemoteServerModulesProxy.CREATE_MODULE_RESPONSE_IS_PERMITTED_PROP, String.valueOf(false) ); ServerModuleStructureRequest.Response response = new ServerModuleStructureRequest.Response(json.toString()); if (clientModuleTime == null) { // If a client has no the resource, let's give it a chance to update the resource, when it will be permitted response.setTimeStamp(new Date(0)); } else { // Let's override client's resource timestamp to guarantee, that permitted == false will be accepted response.setTimeStamp(new Date(clientModuleTime.getTime() + 1000)); } onSuccess.accept(response); } } catch (Exception ex) { onFailure.accept(ex); } } } /** * Checks module roles. * * @param anAllowedRoles * @param aSubjectName * @throws AccessControlException */ public static void checkPrincipalPermission(Set<String> anAllowedRoles, String aSubjectName) throws AccessControlException { if (anAllowedRoles != null && !anAllowedRoles.isEmpty()) { try { PlatypusPrincipal principal = (PlatypusPrincipal) Scripts.getContext().getPrincipal(); if (principal == null || !principal.hasAnyRole(anAllowedRoles)) { throw new AccessControlException(String.format("Access denied to %s for '%s'.",//NOI18N aSubjectName, principal != null ? principal.getName() : null), principal instanceof AnonymousPlatypusPrincipal ? new AuthPermission("*") : null); } } catch (Exception ex) { if (ex instanceof AccessControlException) { throw ex; } else { throw new AccessControlException(ex.getMessage()); } } } } }