package com.baasbox.commands; import java.io.IOException; import java.util.List; import org.apache.commons.lang.exception.ExceptionUtils; import com.baasbox.BBConfiguration; import com.baasbox.commands.exceptions.CommandException; import com.baasbox.commands.exceptions.CommandExecutionException; import com.baasbox.commands.exceptions.CommandNotSupportedException; import com.baasbox.commands.exceptions.CommandParsingException; import com.baasbox.db.DbHelper; import com.baasbox.security.ISessionTokenProvider; import com.baasbox.security.SessionKeys; import com.baasbox.security.SessionTokenProvider; import com.baasbox.service.logging.BaasBoxLogger; import com.baasbox.service.scripting.base.JsonCallback; import com.baasbox.service.scripting.js.Json; import com.baasbox.service.scripting.js.Json.ObjectMapperExt; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.IntNode; import com.fasterxml.jackson.databind.node.NullNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.ImmutableMap; public class SessionsResource extends BaseRestResource { public static final Resource INSTANCE = new SessionsResource(); private static final String RESOURCE_NAME = "sessions"; public static final String TOKEN = "token"; public static final String PASSWORD = "password"; public static final String USERNAME = "username"; @Override protected ImmutableMap.Builder<String, ScriptCommand> baseCommands() { return super.baseCommands().put("revokeAllTokensOfAGivenUser", new ScriptCommand() { @Override public JsonNode execute(JsonNode command, JsonCallback unused) throws CommandException { return revokeAllTokensOfAGivenUser(command); } }).put("getCurrent", this::getCurrent); } protected JsonNode getCurrent(JsonNode command,JsonCallback unused) throws CommandException { try { ImmutableMap<SessionKeys, ? extends Object> st = SessionTokenProvider.getSessionTokenProvider().getCurrent(); if (st==null) return NullNode.getInstance(); ObjectMapperExt mapper = Json.mapper(); String s; s = mapper.writeValueAsString(st); ObjectNode stToRet = (ObjectNode) mapper.readTree(s); stToRet.remove(SessionKeys.PASSWORD.toString()); return stToRet; } catch (JsonProcessingException e) { if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug(ExceptionUtils.getMessage(e),e); throw new CommandExecutionException(command,ExceptionUtils.getMessage(e),e); } catch (IOException e) { if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug(ExceptionUtils.getMessage(e),e); throw new CommandExecutionException(command,ExceptionUtils.getMessage(e),e); } } protected JsonNode revokeAllTokensOfAGivenUser(JsonNode command) throws CommandException { try { super.validateHasParams(command); String username=getUsernameFromParam(command); ISessionTokenProvider tp = SessionTokenProvider .getSessionTokenProvider(); List<ImmutableMap<SessionKeys, ? extends Object>> sessions = tp.getSessions(username); sessions.forEach(x->tp.removeSession((String)x.get(SessionKeys.TOKEN))); return IntNode.valueOf(sessions.size()); } catch (CommandParsingException e){ if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug(ExceptionUtils.getMessage(e),e); throw e; } } /*** * Remove a session value by its token */ @Override protected JsonNode delete(JsonNode command) throws CommandException { try { super.validateHasParams(command); String token=getTokenFromParam(command); SessionTokenProvider .getSessionTokenProvider() .removeSession(token); return NullNode.getInstance(); } catch (CommandParsingException e){ if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug(ExceptionUtils.getMessage(e),e); throw e; } } @Override protected JsonNode put(JsonNode command) throws CommandException { throw new CommandNotSupportedException(command, "It is not possible to update a Session"); } /** * Creates a new session */ @Override protected JsonNode post(JsonNode command) throws CommandException { try { super.validateHasParams(command); String username=getUsernameFromParam(command); String password=getPasswordFromParam(command); ImmutableMap<SessionKeys, ? extends Object> st = SessionTokenProvider.getSessionTokenProvider().setSession(DbHelper.getCurrentAppCode(), username, password); ObjectMapperExt mapper = Json.mapper(); String s=mapper.writeValueAsString(st); ObjectNode stToRet = (ObjectNode) mapper.readTree(s); stToRet.remove(SessionKeys.PASSWORD.toString()); return stToRet; } catch (JsonProcessingException e) { if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug(ExceptionUtils.getMessage(e),e); throw new CommandExecutionException(command,ExceptionUtils.getMessage(e),e); } catch (CommandParsingException e){ if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug(ExceptionUtils.getMessage(e),e); throw e; } catch (IOException e) { if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug(ExceptionUtils.getMessage(e),e); throw new CommandExecutionException(command,ExceptionUtils.getMessage(e),e); } } private String getPasswordFromParam(JsonNode command) throws CommandParsingException { JsonNode passwordNode = super.getParamField(command, PASSWORD); if (passwordNode == null || !passwordNode.isTextual()){ throw new CommandParsingException(command,"invalid \"password\" param: "+(passwordNode==null?"null":passwordNode.toString())); } return passwordNode.asText(); } /** * Returns an Array of session related to a given user */ @Override protected JsonNode list(JsonNode command) throws CommandException { try { super.validateHasParams(command); String username=getUsernameFromParam(command); List<ImmutableMap<SessionKeys, ? extends Object>> sessions = SessionTokenProvider .getSessionTokenProvider() .getSessions(username); ObjectMapperExt mapper = Json.mapper(); String s=mapper.writeValueAsString(sessions); ArrayNode lst = (ArrayNode) mapper.readTree(s); lst.forEach((j)->((ObjectNode)j).remove(SessionKeys.PASSWORD.toString())); return lst; } catch (JsonProcessingException e) { if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug(ExceptionUtils.getMessage(e),e); throw new CommandExecutionException(command,ExceptionUtils.getMessage(e),e); } catch (CommandParsingException e){ if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug(ExceptionUtils.getMessage(e),e); throw e; } catch (IOException e) { if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug(ExceptionUtils.getMessage(e),e); throw new CommandExecutionException(command,ExceptionUtils.getMessage(e),e); } } @Override protected JsonNode get(JsonNode command) throws CommandException { // TODO Auto-generated method stub return null; } @Override public String name() { return RESOURCE_NAME; } private String getTokenFromParam(JsonNode command) throws CommandParsingException { JsonNode tokenNode = super.getParamField(command, TOKEN); if (tokenNode == null || !tokenNode.isTextual()){ throw new CommandParsingException(command,"invalid \"token\" param: "+(tokenNode==null?"null":tokenNode.toString())); } return tokenNode.asText(); } private String getUsernameFromParam(JsonNode command) throws CommandParsingException { JsonNode usernameNode = super.getParamField(command, USERNAME); if (usernameNode == null || !usernameNode.isTextual()){ throw new CommandParsingException(command,"invalid \"username\" param: "+(usernameNode==null?"null":usernameNode.toString())); } String username=usernameNode.asText(); if (username.equalsIgnoreCase(BBConfiguration.getBaasBoxAdminUsername()) || username.equalsIgnoreCase(BBConfiguration.getBaasBoxUsername())){ throw new CommandParsingException(command,"invalid \"username\" param: "+username+" it is reserved"); } return usernameNode.asText(); } }