All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fivefaces.structureclient.controller.WorkflowFacingApiController Maven / Gradle / Ivy

There is a newer version: 1.0.62
Show newest version
package com.fivefaces.structureclient.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fivefaces.cloud.chat.MeetingService;
import com.fivefaces.cloud.sms.SMSService;
import com.fivefaces.common.exception.ItemNotFoundException;
import com.fivefaces.integration.MessageTransmitter;
import com.fivefaces.setting.entity.Setting;
import com.fivefaces.setting.service.SettingService;
import com.fivefaces.structure.query.builder.StructureQuery;
import com.fivefaces.structure.query.builder.criteria.BasicCriteria;
import com.fivefaces.structure.schema.StructureSchema;
import com.fivefaces.structure.service.CsvParser;
import com.fivefaces.structure.service.CsvSchema;
import com.fivefaces.structure.service.StructureSchemaCommitter;
import com.fivefaces.structure.service.StructureSchemaLoader;
import com.fivefaces.structure.service.StructureSchemaValidator;
import com.fivefaces.structure.service.StructureService;
import com.fivefaces.structureclient.domain.StructureSchemaWorkflowScaffold;
import com.fivefaces.structureclient.service.statemachine.ScaffoldStateMachineResult;
import com.fivefaces.structureclient.service.statemachine.ScaffoldStateMachineService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.everit.json.schema.ValidationException;
import org.json.JSONObject;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import static com.fivefaces.structureclient.config.security.SecurityConstants.WORKFLOW_API_PATH;

@RestController
@RequiredArgsConstructor
@Slf4j
@RequestMapping(value = WORKFLOW_API_PATH + "/v1", produces = MediaType.APPLICATION_JSON_VALUE)
public class WorkflowFacingApiController extends AbstractStructureController {

    private static final String ALLOWED_NUMBERS = "0123456789";

    private final ScaffoldStateMachineService scaffoldStateMachineService;
    private final StructureSchemaLoader structureSchemaLoader;
    private final StructureSchemaCommitter structureSchemaCommitter;
    private final StructureSchemaWorkflowScaffold structureSchemaWorkflowScaffold;

    private final StructureService structureService;
    private final StructureSchemaValidator structureSchemaValidator;
    private final CsvParser csvParser;
    private final SMSService smsService;
    private final MeetingService meetingService;
    private final MessageTransmitter messageTransmitter;
    private final SettingService settingService;
    private SecureRandom secureRandom;

    @PostConstruct
    public void setup() {
        try {
            this.secureRandom = SecureRandom.getInstanceStrong();
        } catch (NoSuchAlgorithmException e) {
            this.secureRandom = new SecureRandom();
        }
    }

    @PostMapping("/echo")
    @ResponseBody
    public ResponseEntity handleEcho(@RequestBody final String query) {
        log.info("ECHO\n" + query);
        return ResponseEntity.ok(query);
    }

    @PostMapping("/query")
    @ResponseBody
    public ResponseEntity>> handleQuery(@RequestBody final String query) {
        log.info("/query\n" + query);
        return ResponseEntity.ok(query(StructureQuery.fromJson(query).build()));
    }

    @PostMapping("/count")
    @ResponseBody
    public ResponseEntity handleCount(@RequestBody final String query) {
        log.info("/count\n" + query);
        return ResponseEntity.ok(count(StructureQuery.fromJson(query).build()));
    }

    @PostMapping("/namedQuery")
    @ResponseBody
    public ResponseEntity>> handleNamedQuery(@RequestBody final Map input) {
        log.info("/namedQuery\n" + new JSONObject(input));
        Setting sqlQuery = settingService.getSettingByName("NamedQuery " + input.get("queryName"));
        return ResponseEntity.ok(namedQuery(sqlQuery.getValue(), (Map) input.get("params")));
    }

    @PostMapping("/queries")
    @ResponseBody
    public ResponseEntity>>> handleQueries(@RequestBody final String queries) {
        Map>> results = queries(queries);
        return ResponseEntity.ok(results);
    }

    /**
     * This is designed to be called from an express / synchronous workflow to perform a validation.
     * 

* The settings server is called upon to get the Json Schema to validate the query against. If there is no schema * defined in the settings, then an empty validation is performed *

* { * "type" : "Note", * "workflow":"Collateral", *

* "query" : { * "name" : "name of the collateral", * "note" : "note desc", * "description":"description", * "associations" : [], * "attachments" : [] * } * } * * @param insertJSON The json input as string such as example above * @return The created structure as json */ @PostMapping("/insert") @ResponseBody public ResponseEntity insert(@RequestBody final String insertJSON) { log.info("/insert\n" + insertJSON); JSONObject entityJSON = new JSONObject(insertJSON); String username = entityJSON.getString("username"); if (StringUtils.isBlank(username)) { throw new IllegalArgumentException("Username missing"); } try { Map insert = structureService.insert(username, entityJSON); return ResponseEntity.ok(String.format("{\"id\":\"%s\"}", insert.get("id"))); } catch (Exception e) { log.error(e.getMessage(), e); return ResponseEntity.badRequest().build(); } } @PostMapping("/persist") @ResponseBody public ResponseEntity persist(@RequestBody final String persistJSON) { log.info("/persist\n" + persistJSON); JSONObject entityJSON = new JSONObject(persistJSON); String username = entityJSON.getString("username"); if (StringUtils.isBlank(username)) { throw new IllegalArgumentException("Username missing"); } try { return ResponseEntity.ok(structureService.persist(username, entityJSON)); } catch (Exception e) { log.error(e.getMessage()); return ResponseEntity.badRequest().build(); } } @PostMapping("/unsecuredCall") @ResponseBody public ResponseEntity unsecuredCall(@RequestBody final String json) { log.info("/unsecuredCall\n" + json); return ResponseEntity.ok(json); } @PostMapping("/id") @ResponseBody public ResponseEntity> id(@RequestParam(required = false, defaultValue = "1") int count) { List result = new ArrayList<>(); for (int i = 0; i < count; i++) { result.add(UUID.randomUUID().toString()); } return ResponseEntity.ok(result); } @PostMapping("/otp") @ResponseBody public ResponseEntity> otp(@RequestParam(required = false, defaultValue = "6") int length, @RequestParam(required = false, defaultValue = "1") int count) { List result = new ArrayList<>(); for (int i = 0; i < count; i++) { result.add(RandomStringUtils.random(length, 0, 0, false, true, ALLOWED_NUMBERS.toCharArray(), secureRandom)); } return ResponseEntity.ok(result); } @PostMapping("/update") @ResponseBody public ResponseEntity update(@RequestBody final String updateJson) { log.info("/update\n" + updateJson); JSONObject entityJSON = new JSONObject(updateJson); String username = entityJSON.getString("username"); if (StringUtils.isBlank(username)) { throw new IllegalArgumentException("Username missing"); } try { final String result = structureService.update(username, entityJSON); return ResponseEntity.ok(result); } catch (Exception e) { log.error(e.getMessage(), e); return ResponseEntity.badRequest().build(); } } @PostMapping("/validate") @ResponseBody public ResponseEntity validateFromSyncWorkflow(@RequestBody final String validateJSON) { log.info("/validate\n" + validateJSON); try { JSONObject json = new JSONObject(validateJSON); JSONObject query = json.getJSONObject("query"); String type = null; String updateId = null; if (json.has("type")) { type = json.getString("type"); } if (json.has("updateId")) { updateId = json.getString("updateId"); } JSONObject jsonSchema = json.getJSONObject("schema"); structureSchemaValidator.validate(type, updateId, query, jsonSchema); } catch (ValidationException exception) { log.info(exception.getMessage()); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(StringUtils.join(exception.getAllMessages(), "\n")); } catch (Exception exception) { log.info(exception.getMessage()); return ResponseEntity.badRequest().build(); } log.info("no validation issues"); return ResponseEntity.ok().build(); } @PostMapping("/delete") @ResponseBody public ResponseEntity delete(@RequestBody final String query) { log.info("/delete\n" + query); try { structureService.delete(new JSONObject(query)); return ResponseEntity.ok().build(); } catch (Exception e) { return ResponseEntity.badRequest().build(); } } @PostMapping("/sms") @ResponseBody public ResponseEntity sendSms(@RequestBody final Map smsRequest) { log.info("Sending Sms"); smsService.sendSms(smsRequest.get("mobilePhone"), smsRequest.get("message")); return ResponseEntity.ok().build(); } @PostMapping("/getJsonFromCsv") @ResponseBody public ResponseEntity getJsonFromCsv( @RequestBody final String content) { log.info("/getJsonFromCsv\n" + content); final JSONObject jsonObject = new JSONObject(content); try { CsvSchema csvSchema = new CsvSchema(); List headerSwaps = getRequestHeaderSwaps(jsonObject); csvSchema.setHeaderSwaps(headerSwaps); final String result = csvParser.getJsonFromCsv( jsonObject.getString("csvContent"), csvSchema); return ResponseEntity.ok(result); } catch (Exception exception) { log.info(exception.getMessage()); return ResponseEntity.badRequest().build(); } } @PostMapping("/hasAnyRole") @ResponseBody public ResponseEntity userHasRole(@RequestBody Map> request) { log.info("/hasAnyRole\n" + request); List requiredRoles = request.get("requiredRoles"); List userRoles = request.get("userRoles"); boolean authorized = false; for (String requiredRole : requiredRoles) { if (userRoles.contains(requiredRole)) { authorized = true; break; } } if (authorized) { return ResponseEntity.ok("{\"status\":\"Authorized\"}"); } return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("{\"status\":\"Not Authorized\"}"); } @PostMapping("/createOnlineMeeting") @ResponseBody public ResponseEntity createOnlineMeeting(@RequestBody final String jsonCreateOnlineMeeting) { log.info("/createOnlineMeeting\n" + jsonCreateOnlineMeeting); final JSONObject json = new JSONObject(jsonCreateOnlineMeeting); final String result = meetingService.createOnlineMeeting(json.getJSONObject("query")); return ResponseEntity.ok(result); } @PostMapping("/deleteOnlineMeeting") @ResponseBody public ResponseEntity deleteOnlineMeeting(@RequestBody final String jsonDeleteOnlineMeeting) { log.info("/deleteOnlineMeeting\n" + jsonDeleteOnlineMeeting); final JSONObject json = new JSONObject(jsonDeleteOnlineMeeting); meetingService.deleteOnlineMeeting(json.getJSONObject("query")); return ResponseEntity.ok().build(); } @PostMapping("/getQueueWithService") @ResponseBody public ResponseEntity handleGetQueueWithService(@RequestBody final String jsonInput) { final List jsonValues = geQueueWithService(jsonInput); return ResponseEntity.ok(jsonValues.get(0).toString()); } @PostMapping("/transmit") @ResponseBody public ResponseEntity transmitMessage(@RequestBody final String payload) { JSONObject jsonObject = new JSONObject(payload); String responseBody; try { responseBody = messageTransmitter.transmitMessage(jsonObject); return ResponseEntity.ok(responseBody); } catch (Exception e) { return ResponseEntity.badRequest().build(); } } @PostMapping("/transform-workflow-definition") @ResponseBody public ResponseEntity> transformWorkflowDefinition(@RequestBody Map input) throws Exception { Map query = (Map) input.get("query"); if (query.containsKey("functionSource") && StringUtils.isNotBlank((String) query.get("functionSource"))) { String functionSource = (String) query.get("functionSource"); ScaffoldStateMachineResult result = scaffoldStateMachineService.scaffold(functionSource); Map machine = new ObjectMapper().readValue(result.getStateMachines().get("nameOfTheStateMachine"), Map.class); query.put("functionDefinition", machine); } return ResponseEntity.ok(input); } @PostMapping("/destroy-structure") @ResponseBody public ResponseEntity destroyStructure(@RequestBody Map payload) throws Exception { String id = (String) payload.get("id"); List> existingStructure = structureService.queryById("structureDefinition", UUID.fromString(id)); if (CollectionUtils.isEmpty(existingStructure)) { throw new ItemNotFoundException("No structure with this id"); } String structureName = (String) existingStructure.get(0).get("name"); destroyStructureByName(structureName); return ResponseEntity.ok("{\"status\":\"OK\"}"); } @PostMapping("/destroy-structure-name") @ResponseBody public ResponseEntity destroyStructureName(@RequestBody Map payload) throws Exception { destroyStructureByName((String) payload.get("name")); return ResponseEntity.ok("{\"status\":\"OK\"}"); } @PostMapping("/create-structure") @ResponseBody public ResponseEntity createStructure(@RequestBody Map payload) throws Exception { String structureName = (String) payload.get("name"); structureSchemaLoader.reloadStructureSchemas(); StructureSchema structureSchema = structureSchemaLoader.getTargetSchemas().get(structureName); if (structureSchema == null) { throw new ItemNotFoundException(structureName + " is not defined"); } structureSchemaCommitter.recreateTableForSchema(structureSchema); Map workflows = structureSchemaWorkflowScaffold.scaffold(structureSchema); workflows.forEach((key, value) -> { try { JSONObject capsule = new JSONObject(); capsule.put("type", "workflow"); capsule.put("query", new JSONObject(value)); structureService.insert("APP_BUILDER", capsule); } catch (Exception e) { throw new RuntimeException(e); } }); return ResponseEntity.ok("{\"status\":\"OK\"}"); } private void destroyStructureByName(String structureName) throws Exception { structureSchemaLoader.reloadStructureSchemas(); StructureSchema structureSchema = structureSchemaLoader.getLiveSchemas().get(structureName); if (structureSchema == null) { return; } structureSchemaCommitter.dropTableForSchema(structureSchema); Map workflows = structureSchemaWorkflowScaffold.scaffold(structureSchema); structureService.delete(StructureQuery.builder() .type("workflow") .criteria(BasicCriteria.builder() .member("$.name").type("in").value(workflows.keySet())) .build()); structureService.delete(StructureQuery.builder() .type("structureDefinition") .criteria(BasicCriteria.builder() .member("$.name").type("eq").value(structureName)) .build()); } private List getRequestHeaderSwaps(JSONObject jsonObject) { List headerSwaps = new ArrayList<>(); if (!jsonObject.has("headerSwaps")) { return headerSwaps; } for (Object headerSwap : jsonObject.getJSONArray("headerSwaps")) { headerSwaps.add((String) headerSwap); } return headerSwaps; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy