diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index 57906d4a391..51cd044ad4f 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -34,10 +34,6 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 200 services: - mongo: - image: mongo:4.4 - ports: - - 27017:27017 redis: image: redis @@ -52,12 +48,45 @@ jobs: options: -e="discovery.type=single-node" -e="xpack.security.enabled=false" --health-cmd="curl http://localhost:9200/_cluster/health" --health-interval=10s --health-timeout=5s --health-retries=10 steps: + - name: Start MongoDB + uses: MongoCamp/mongodb-github-action@1.2.0 + with: + mongodb-version: 4.4 + mongodb-replica-set: rs0 + + - name: Wait for Elasticsearch to be ready + run: | + echo "Waiting for Elasticsearch to be ready..." + for i in {1..30}; do + if curl -fsSL http://localhost:9200/_cluster/health | grep '"status":"green"' &>/dev/null; then + echo "Elasticsearch is up" + break + fi + echo "Waiting for Elasticsearch..." + sleep 2 + done + + - name: Wait for MongoDB to be ready + run: | + echo "Waiting for MongoDB to be ready..." + for i in {1..30}; do + if mongo --eval "printjson(db.serverStatus())" &>/dev/null; then + echo "MongoDB is up" + break + fi + echo "Waiting for MongoDB..." + sleep 2 + done + - name: Test Database env: ELASTIC_SEARCH_URL: http://localhost:${{ job.services.elasticsearch.ports[9200] }} + MONGO_URL: http://localhost:27017 run: | echo $ELASTIC_SEARCH_URL + echo $MONGO_URL curl -fsSL "$ELASTIC_SEARCH_URL/_cat/health?h=status" + curl -fsSL "$MONGO_URL" - uses: actions/checkout@v3 with: @@ -69,12 +98,12 @@ jobs: java-version: 11 distribution: 'adopt' -# - name: Cache SonarCloud packages -# uses: actions/cache@v3 -# with: -# path: ~/.sonar/cache -# key: ${{ runner.os }}-sonar -# restore-keys: ${{ runner.os }}-sonar + # - name: Cache SonarCloud packages + # uses: actions/cache@v3 + # with: + # path: ~/.sonar/cache + # key: ${{ runner.os }}-sonar + # restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages uses: actions/cache@v3 @@ -86,17 +115,16 @@ jobs: - name: Generate certificates run: cd src/main/resources/certificates && openssl genrsa -out keypair.pem 4096 && openssl rsa -in keypair.pem -pubout -out public.crt && openssl pkcs8 -topk8 -inform PEM -outform DER -nocrypt -in keypair.pem -out private.der && cd ../../../.. - - name: Build run: mvn clean package install -DskipTests=true -# Upgrade Java -# - name: Build, test, and analyze -# timeout-minutes: 180 -# env: -# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} -# run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=netgrif_application-engine + # Upgrade Java + # - name: Build, test, and analyze + # timeout-minutes: 180 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + # run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=netgrif_application-engine - name: Build, test timeout-minutes: 180 diff --git a/docker-compose.yml b/docker-compose.yml index e8f9e97c2c6..c2c7aa8ba82 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,8 +3,15 @@ version: "3.3" services: docker-mongo: image: mongo:4.4 + command: [ "--replSet", "rs0", "--bind_ip_all", "--port", "27017" ] + hostname: 127.0.0.1 ports: - "27017:27017" + healthcheck: + test: echo "try { rs.status() } catch (err) { rs.initiate({_id:'rs0',members:[{_id:0,host:'host.docker.internal:27017'}]}) }" | mongosh --port 27017 --quiet + interval: 5s + timeout: 30s + retries: 10 deploy: resources: limits: diff --git a/pom.xml b/pom.xml index 31213b1ecce..18f8e47872f 100644 --- a/pom.xml +++ b/pom.xml @@ -527,6 +527,7 @@ + com.netgrif.application.engine.importer.model ${project.build.directory}/generated-sources/java diff --git a/src/main/groovy/com/netgrif/application/engine/DevConsole.groovy b/src/main/groovy/com/netgrif/application/engine/DevConsole.groovy index ab786315cf7..9e013a8d11f 100644 --- a/src/main/groovy/com/netgrif/application/engine/DevConsole.groovy +++ b/src/main/groovy/com/netgrif/application/engine/DevConsole.groovy @@ -1,6 +1,5 @@ package com.netgrif.application.engine -import com.netgrif.application.engine.importer.model.Document import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import groovy.util.logging.Slf4j @@ -11,9 +10,6 @@ import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController -import javax.xml.bind.JAXBContext -import javax.xml.bind.Marshaller -import javax.xml.bind.Unmarshaller import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE import static org.springframework.http.MediaType.APPLICATION_XML_VALUE @@ -34,48 +30,49 @@ class DevConsole { @GetMapping(value = "/dataset/{title}", produces = APPLICATION_JSON_VALUE) String dataset(@PathVariable String title) { def useCase = caseRepository.findAll().find { it.title == title } - return "{ ${useCase?.dataSet?.collect { "\"${useCase?.petriNet?.dataSet?.get(it?.key)?.importId}:${useCase?.petriNet?.dataSet?.get(it?.key)?.name?.toString()?.replaceAll("\n[ ]{2}", "")}\":\"${it?.value?.value as String}\"" }?.join(", ")} }" + return "{ ${useCase?.dataSet?.collect { "\"${useCase?.process?.dataSet?.get(it?.key)?.importId}:${useCase?.process?.dataSet?.get(it?.key)?.title?.toString()?.replaceAll("\n[ ]{2}", "")}\":\"${it?.value?.value as String}\"" }?.join(", ")} }" } @GetMapping(value = "/net/{title}", produces = APPLICATION_XML_VALUE) String netSnapshot(@PathVariable String title) { - try { - def useCase = caseRepository.findAll().find { it.title == title } - def net = useCase.petriNet - def xml = new File(net.importXmlPath) - - JAXBContext jaxbContext = JAXBContext.newInstance(Document.class) - Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller() - Document document = (Document) jaxbUnmarshaller.unmarshal(xml) - - document.getImportPlaces().each { importPlace -> - importPlace.tokens = useCase.activePlaces.get(net.places.values().find { - it.importId == importPlace.id - }.getStringId()) - if (importPlace.tokens == null) - importPlace.tokens = 0 - } - document.getImportData().each { - it.action = null - it.values = null - it.documentRefs = null - } - document.getImportTransitions().each { - it.dataGroup = null - } - document.importRoles = null - document.importTransactions = null - document.importData = null - - Marshaller marshaller = jaxbContext.createMarshaller() - StringWriter stringWriter = new StringWriter() - marshaller.marshal(document, stringWriter) - - return stringWriter.toString() - } catch (Exception ignored) { - log.error("Getting snapshot of net failed: ", ignored) + // TODO: NAE-1969 fix +// try { +// def useCase = caseRepository.findAll().find { it.title == title } +// def net = useCase.petriNet +// def xml = new File(net.importXmlPath) +// +// JAXBContext jaxbContext = JAXBContext.newInstance(Document.class) +// Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller() +// Document document = (Document) jaxbUnmarshaller.unmarshal(xml) +// +// document.getImportPlaces().each { importPlace -> +// importPlace.tokens = useCase.activePlaces.get(net.places.values().find { +// it.importId == importPlace.id +// }.getStringId()) +// if (importPlace.tokens == null) +// importPlace.tokens = 0 +// } +// document.getImportData().each { +// it.action = null +// it.values = null +// it.documentRefs = null +// } +// document.getImportTransitions().each { +// it.dataGroup = null +// } +// document.importRoles = null +// document.importTransactions = null +// document.importData = null +// +// Marshaller marshaller = jaxbContext.createMarshaller() +// StringWriter stringWriter = new StringWriter() +// marshaller.marshal(document, stringWriter) +// +// return stringWriter.toString() +// } catch (Exception ignored) { +// log.error("Getting snapshot of net failed: ", ignored) return null - } +// } } } diff --git a/src/main/groovy/com/netgrif/application/engine/migration/ActionMigration.groovy b/src/main/groovy/com/netgrif/application/engine/migration/ActionMigration.groovy index 20228cbce3d..8f0ef575c37 100644 --- a/src/main/groovy/com/netgrif/application/engine/migration/ActionMigration.groovy +++ b/src/main/groovy/com/netgrif/application/engine/migration/ActionMigration.groovy @@ -1,10 +1,11 @@ package com.netgrif.application.engine.migration -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.authorization.service.interfaces.IUserService +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome import groovy.util.logging.Slf4j import org.springframework.beans.factory.annotation.Autowired import org.springframework.core.io.ClassPathResource @@ -20,49 +21,50 @@ class ActionMigration { private IPetriNetService petriNetService @Autowired - private IUserService userService; + private IUserService userService void migrateActions(String petriNetPath) { InputStream netStream = new ClassPathResource(petriNetPath).inputStream - ImportPetriNetEventOutcome newPetriNet = petriNetService.importPetriNet(netStream, VersionType.MAJOR, userService.loggedOrSystem.transformToLoggedUser()) - List oldPetriNets + ImportPetriNetEventOutcome newPetriNet = petriNetService.importProcess(new ImportProcessParams(netStream, VersionType.MAJOR, + userService.getSystemUser().stringId)) + List oldPetriNets - if(newPetriNet.getNet() != null) { + if(newPetriNet.getProcess() != null) { String message = "Petri net from file [" + petriNetPath + "] was not imported" log.error(message) throw new IllegalArgumentException(message) } else { - oldPetriNets = petriNetService.getByIdentifier(newPetriNet.getNet().importId) - .stream().filter({ net -> (net.version != newPetriNet.getNet().version)}) + oldPetriNets = petriNetService.getByIdentifier(newPetriNet.getProcess().importId) + .stream().filter({ net -> (net.version != newPetriNet.getProcess().version)}) .collect(Collectors.toList()) } if(oldPetriNets.size() == 0){ - String message = "Older version of Petri net with ID [" + newPetriNet.getNet().importId + "] is not present in MongoDB." + String message = "Older version of Petri net with ID [" + newPetriNet.getProcess().importId + "] is not present in MongoDB." log.error(message) throw new IllegalArgumentException(message) } else { oldPetriNets.each {net -> - migrateDataSetActions(newPetriNet.getNet(), net) - migrateDataRefActions(newPetriNet.getNet(), net) + migrateDataSetActions(newPetriNet.getProcess(), net) + migrateDataRefActions(newPetriNet.getProcess(), net) petriNetService.save(net) } } } - private void migrateDataSetActions(PetriNet newPetriNet, PetriNet oldPetriNet) { + private void migrateDataSetActions(Process newPetriNet, Process oldPetriNet) { newPetriNet.dataSet.each { key, data -> if (data.events != null && data.events.size() > 0) { - oldPetriNet.dataSet[key].events = data.events + oldPetriNet.dataSet.get(key).events = data.events } } } - private void migrateDataRefActions(PetriNet newPetriNet, PetriNet oldPetriNet) { + private void migrateDataRefActions(Process newPetriNet, Process oldPetriNet) { newPetriNet.transitions.each { transKey, trans -> trans.dataSet.each { dataKey, data -> if (data.events != null && data.events.size() > 0) { - oldPetriNet.transitions[transKey].dataSet[dataKey].events = data.events + oldPetriNet.transitions.get(transKey).dataSet.get(dataKey).events = data.events } } } diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionAPI.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionAPI.groovy index d97517f9e06..7b6150ab68a 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionAPI.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionAPI.groovy @@ -1,7 +1,7 @@ package com.netgrif.application.engine.petrinet.domain.dataset.logic.action import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.Task import com.querydsl.core.types.Predicate @@ -36,7 +36,7 @@ interface ActionAPI { Case createCase(ObjectId netId) - Case createCase(PetriNet net) + Case createCase(Process net) setData(Field, Map) diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index f00157c40fa..14b0e45d2a8 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -2,13 +2,21 @@ package com.netgrif.application.engine.petrinet.domain.dataset.logic.action import com.netgrif.application.engine.AsyncRunner -import com.netgrif.application.engine.auth.domain.Author -import com.netgrif.application.engine.auth.domain.IUser -import com.netgrif.application.engine.auth.domain.LoggedUser -import com.netgrif.application.engine.auth.service.UserDetailsServiceImpl -import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.auth.web.requestbodies.NewUserRequest +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.LoggedIdentity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authentication.service.UserDetailsServiceImpl +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authentication.service.interfaces.IRegistrationService + +import com.netgrif.application.engine.authentication.web.requestbodies.NewIdentityRequest +import com.netgrif.application.engine.authorization.domain.ProcessRole +import com.netgrif.application.engine.authorization.domain.Role +import com.netgrif.application.engine.authorization.domain.User +import com.netgrif.application.engine.authorization.service.interfaces.IAllActorService +import com.netgrif.application.engine.authorization.service.interfaces.IGroupService +import com.netgrif.application.engine.authorization.service.interfaces.IUserService +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService import com.netgrif.application.engine.configuration.PublicViewProperties import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService @@ -18,32 +26,35 @@ import com.netgrif.application.engine.export.configuration.ExportConfiguration import com.netgrif.application.engine.export.domain.ExportDataConfig import com.netgrif.application.engine.export.service.interfaces.IExportService import com.netgrif.application.engine.history.service.IHistoryService -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService import com.netgrif.application.engine.importer.service.FieldFactory import com.netgrif.application.engine.mail.domain.MailDraft import com.netgrif.application.engine.mail.interfaces.IMailAttemptService import com.netgrif.application.engine.mail.interfaces.IMailService -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService import com.netgrif.application.engine.petrinet.domain.* import com.netgrif.application.engine.petrinet.domain.dataset.* import com.netgrif.application.engine.petrinet.domain.dataset.logic.FieldBehavior -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.domain.version.Version import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.petrinet.service.interfaces.IUriService import com.netgrif.application.engine.rules.domain.RuleRepository import com.netgrif.application.engine.startup.DefaultFiltersRunner import com.netgrif.application.engine.startup.FilterRunner -import com.netgrif.application.engine.utils.FullPageRequest +import com.netgrif.application.engine.transaction.NaeTransaction +import com.netgrif.application.engine.validations.interfaces.IValidationService import com.netgrif.application.engine.workflow.domain.* -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.GetDataEventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.AssignTaskEventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.TaskEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CreateCaseEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.DeleteCaseEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.GetDataEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.AssignTaskEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.TaskEventOutcome import com.netgrif.application.engine.workflow.domain.menu.MenuItemBody import com.netgrif.application.engine.workflow.domain.menu.MenuItemConstants +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams +import com.netgrif.application.engine.workflow.domain.params.DeleteCaseParams +import com.netgrif.application.engine.workflow.domain.params.GetDataParams +import com.netgrif.application.engine.workflow.domain.params.SetDataParams +import com.netgrif.application.engine.workflow.domain.params.TaskParams import com.netgrif.application.engine.workflow.service.FileFieldInputStream import com.netgrif.application.engine.workflow.service.TaskService import com.netgrif.application.engine.workflow.service.interfaces.* @@ -61,10 +72,11 @@ import org.springframework.context.i18n.LocaleContextHolder import org.springframework.data.domain.Page import org.springframework.data.domain.PageRequest import org.springframework.data.domain.Pageable +import org.springframework.data.mongodb.MongoTransactionManager +import org.springframework.transaction.TransactionDefinition import java.text.Normalizer import java.util.stream.Collectors - /** * ActionDelegate class contains Actions API methods. */ @@ -83,7 +95,6 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { public static final String PREFERENCE_ITEM_FIELD_APPEND_MENU_ITEM = "append_menu_item_stringId" public static final String PREFERENCE_ITEM_FIELD_ALLOWED_ROLES = "allowed_roles" public static final String PREFERENCE_ITEM_FIELD_BANNED_ROLES = "banned_roles" - public static final String ORG_GROUP_FIELD_FILTER_TASKS = "filter_tasks" static final String TRANSITIONS = "transitions" @@ -105,6 +116,9 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { @Autowired IWorkflowService workflowService + @Autowired + IIdentityService identityService + @Autowired IUserService userService @@ -117,9 +131,6 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { @Autowired IMailService mailService - @Autowired - INextGroupService nextGroupService - @Autowired IRegistrationService registrationService @@ -129,9 +140,6 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { @Autowired UserDetailsServiceImpl userDetailsService - @Autowired - IDataValidationExpressionEvaluator dataValidationExpressionEvaluator - @Autowired IInitValueExpressionEvaluator initValueExpressionEvaluator @@ -142,7 +150,7 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { Scheduler scheduler @Autowired - IUserFilterSearchService filterSearchService + IActorFilterSearchService filterSearchService @Autowired IConfigurableMenuService configurableMenuService @@ -168,15 +176,27 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { @Autowired IUriService uriService - @Autowired - IImpersonationService impersonationService - @Autowired IHistoryService historyService @Autowired PublicViewProperties publicViewProperties + @Autowired + MongoTransactionManager transactionManager + + @Autowired + IValidationService validationService + + @Autowired + IRoleService roleService + + @Autowired + IGroupService groupService + + @Autowired + IAllActorService allActorService + FrontendActionOutcome Frontend /** @@ -202,13 +222,100 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { this.task = task this.fieldChanges = fieldChanges this.params = params + // TODO: release/8.0.0 init net resources as delegate properties this.actionsRunner = actionsRunner - this.initFieldsMap(action.fieldIds, useCase) - this.initTransitionsMap(action.transitionIds) this.outcomes = new ArrayList<>() this.Frontend = new FrontendActionOutcome(this.useCase, this.task, this.outcomes) } + /** + * Method runs provided code in database transaction. If the provided code fails, the rollback callback is called + * and no exception is thrown. If the callback fails the subject exception is thrown. + *
+ * Simple example: + *
+     *     trans: t.t1,
+     *     text: f.textId;
+     *
+     *     transactional {
+     *         change text value { "some text value" }
+     *         make text, visible on trans when { true }
+     *     }
+     *     createCase("my_process", "My case")
+     * 
+ * Complex example: + *
+     *     trans: t.t1,
+     *     result: f.resultId,
+     *     text: f.textId;
+     *
+     *     def myTransaction = transactional (
+     *          timeout: 1000,
+     *          forceCreation: true,
+     *          event: {
+     *              createCase("my_process", "My case")
+     *              change text value { "some text value" }
+     *          },
+     *          onCommit: {
+     *              make text, editable on trans when { true }
+     *          },
+     *          onRollBack: { error ->
+     *              handleError(error)
+     *          }
+     *     )
+     *     change result value { myTransaction.wasRolledBack }
+     * 
+ * + * @param timeout timeout in milliseconds. If the time is reached, transaction fails. The default value is + * {@link org.springframework.transaction.TransactionDefinition#TIMEOUT_DEFAULT} + * @param forceCreation if set to true, new transaction is created under any situation. If set to false new + * transaction is created only if none transaction is active + * @param event code to be run in transaction + * @param onCommit callback, that is called after the successful commit + * @param onRollBack callback, that is called after event failure + * + * @returns {@link com.netgrif.application.engine.transaction.NaeTransaction} with state after the commit and callback execution + * */ + @NamedVariant + NaeTransaction transaction(int timeout = TransactionDefinition.TIMEOUT_DEFAULT, boolean forceCreation = false, Closure event, + Closure onCommit = null, Closure onRollBack = null) { + def transactionBuilder = NaeTransaction.builder() + .timeout(timeout) + .forceCreation(forceCreation) + .event(event) + .onCommit(onCommit) + .onRollBack(onRollBack) + .transactionManager(transactionManager) + + NaeTransaction transaction = transactionBuilder.build() + executeTransaction(transaction) + throwIfCallBackFailed(transaction) + + return transaction + } + + /** + * Logs and throws an exception if the transaction failed on callback execution. + * + * @param transaction object after the commit / rollback + * */ + protected void throwIfCallBackFailed(NaeTransaction transaction) { + if (transaction.onCallBackException == null){ + return + } + log.error("Transaction synchronization call back execution failed with message: {} ", transaction.onCallBackException.getMessage()) + throw transaction.onCallBackException + } + + protected void executeTransaction(NaeTransaction transaction) { + try { + transaction.begin() + } catch (Exception e) { + log.warn("Transaction failed in action: $action.definition") + log.error("Transaction failed with error: {}", e.getMessage(), e) + } + } + void initFieldsMap(Map fieldIds, Case useCase) { fieldIds.each { name, id -> set(name, useCase.getDataSet().get(id)) @@ -217,7 +324,7 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { def initTransitionsMap(Map transitionIds) { transitionIds.each { name, id -> - set(name, useCase.petriNet.transitions[id]) + set(name, useCase.process.transitions[id]) } } @@ -238,6 +345,20 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { return dataFieldBehavior } + // TODO: docasna metoda na priradenie behavior fieldu (make na 8.0.0 nefunguje) + DataFieldBehaviors createBehavior(String fieldId, FieldBehavior fieldBehavior, String transitionId = task.get().transitionId, Case caze = useCase) { + Field caseField = useCase.dataSet.get(fieldId) + if (caseField.behaviors == null) { + caseField.behaviors = new DataFieldBehaviors() + caze.dataSet.get(fieldId).behaviors.put(transitionId, new DataFieldBehavior()) + } + if (caseField.behaviors.get(transitionId) == null && caze.getPetriNet().getTransition(transitionId) != null && caze.getPetriNet().getTransition(transitionId).dataSet.get(fieldId) != null) { + caseField.behaviors.put(transitionId, caze.getPetriNet().getTransition(transitionId).dataSet.get(fieldId).behavior) + } + caseField.behaviors.behaviors.get(transitionId).behavior = fieldBehavior + return caseField.behaviors + } + def visible = { Field field, Transition trans -> copyBehavior(field, trans) getOrCreateBehavior(field.stringId, trans.stringId).behavior = FieldBehavior.VISIBLE @@ -271,7 +392,7 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { def initial = { Field field, Transition trans -> copyBehavior(field, trans) DataFieldBehavior fieldBehavior = getOrCreateBehavior(field.stringId, trans.stringId) - DataFieldBehavior initialBehavior = useCase?.petriNet?.dataSet?.get(field.importId)?.behaviors?.get(trans?.importId) + DataFieldBehavior initialBehavior = useCase?.process?.dataSet?.get(field.importId)?.behaviors?.get(trans?.importId) if (initialBehavior == null) { initialBehavior = new DataFieldBehavior() } @@ -284,7 +405,7 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { if (!field.hasDefault()) { return null } else if (field.isDynamicDefaultValue()) { - return initValueExpressionEvaluator.evaluate(useCase, field, params) + return initValueExpressionEvaluator.evaluateValue(useCase, field, params) } return field.defaultValue } @@ -421,7 +542,7 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { changeBehaviourAndSave(field, behavior, trans) } } else if (transitionObject instanceof Closure && transitionObject == transitions) { - useCase.petriNet.transitions.each { transitionEntry -> + useCase.process.transitions.map.each { transitionEntry -> changeBehaviourAndSave(field, behavior, transitionEntry.value) } } else { @@ -429,10 +550,10 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { } } - SetDataEventOutcome setData(Field field, Map changes, IUser user = userService.loggedOrSystem) { - SetDataEventOutcome outcome = dataService.setData(useCase, new DataSet([ + SetDataEventOutcome setData(Field field, Map changes, LoggedIdentity identity = identityService.loggedIdentity) { + SetDataEventOutcome outcome = dataService.setData(new SetDataParams(useCase, new DataSet([ (field.stringId): field.class.newInstance(changes) - ] as Map>), user) + ] as Map>), identity.activeActorId)) this.outcomes.add(outcome) updateCase() return outcome @@ -449,7 +570,7 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { // TODO: release/8.0.0 check if needed after merge protected void saveFieldBehaviorWithTask(Field field, Task task, Closure behavior, def behaviorClosureResult) { Case aCase = workflowService.findOne(task.caseId) - Transition transition = aCase.getPetriNet().getTransition(task.getTransitionId()) + Transition transition = aCase.getProcess().getTransition(task.getTransitionId()) behaviorClosureResult = behavior(field, transition, aCase) saveFieldBehavior(field, transition, (behavior == initial) ? behaviorClosureResult as Set : null, aCase, Optional.of(task)) } @@ -474,7 +595,7 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { def execute(String taskId) { [with : { DataSet dataSet -> - executeTasks(dataSet, taskId, { it.id.isNotNull() }) + executeTasks(dataSet, taskId, { it.setStringId.isNotNull() }) }, where: { Closure closure -> [with: { DataSet dataSet -> @@ -485,7 +606,7 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { def execute(Task task) { [with : { DataSet dataSet -> - executeTasks(dataSet, task.stringId, { it.id.isNotNull() }) + executeTasks(dataSet, task.stringId, { it.setStringId.isNotNull() }) }, where: { Closure closure -> [with: { DataSet dataSet -> @@ -510,9 +631,9 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { } private addTaskOutcomes(Task task, DataSet dataSet) { - this.outcomes.add(taskService.assignTask(task.stringId)) - this.outcomes.add(dataService.setData(task.stringId, dataSet, userService.loggedOrSystem)) - this.outcomes.add(taskService.finishTask(task.stringId)) + this.outcomes.add(taskService.assignTask(new TaskParams(task.stringId))) + this.outcomes.add(dataService.setData(new SetDataParams(task.stringId, dataSet, identityService.loggedIdentity.activeActorId))) + this.outcomes.add(taskService.finishTask(new TaskParams(task.stringId))) } List searchCases(Closure predicates) { @@ -533,7 +654,7 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { if (taskId != null) { targetTask = taskService.findOne(taskId) } - Field field = targetCase.getPetriNet().getDataSet().get(fieldId) + Field field = targetCase.getProcess().getDataSet().get(fieldId) // TODO: release/8.0.0 missing change(field, targetCase, Optional.of(targetTask)) } @@ -653,6 +774,9 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { if (value != null) { // TODO: release/8.0.0 should be in data service if (field instanceof CaseField) { + if (value.every {it == null}) { + return; + } value = ((List) value).stream().map({ entry -> entry instanceof Case ? entry.getStringId() : entry }).collect(Collectors.toList()) dataService.validateCaseRefValue((List) value, ((CaseField) field).getAllowedNets()) } @@ -661,7 +785,11 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { } if (field instanceof UserListField && (value instanceof String[] || value instanceof List)) { LinkedHashSet users = new LinkedHashSet<>() - value.each { id -> users.add(new UserFieldValue(userService.findById(id as String))) } + value.each { id -> + Optional userOpt = userService.findById(id as String) + UserFieldValue userFieldValue = userOpt.isPresent() ? new UserFieldValue(userOpt.get()) : new UserFieldValue() + users.add(userFieldValue) + } value = new UserListFieldValue(users) } if (value instanceof GString) { @@ -709,43 +837,97 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { return workflowService.searchOne(predicate(qCase)) } - Case createCase(String identifier, String title = null, String color = "", IUser author = userService.loggedOrSystem, Locale locale = LocaleContextHolder.getLocale(), Map params = [:]) { - return workflowService.createCaseByIdentifier(identifier, title, color, author.transformToLoggedUser(), locale, params).getCase() - } - - Case createCase(PetriNet net, String title = net.defaultCaseName.getTranslation(locale), String color = "", IUser author = userService.loggedOrSystem, Locale locale = LocaleContextHolder.getLocale(), Map params = [:]) { - CreateCaseEventOutcome outcome = workflowService.createCase(net.stringId, title, color, author.transformToLoggedUser(), params) + Case createCase(String identifier, String title = null, String color = "", LoggedIdentity author = identityService.loggedIdentity, + Locale locale = LocaleContextHolder.getLocale(), Map params = [:]) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(identifier) + .title(title) + .authorId(author.activeActorId) + .params(params) + .build() + return workflowService.createCase(createCaseParams).getCase() + } + + Case createCase(Process net, String title = net.defaultCaseName.getTranslation(locale), String color = "", LoggedIdentity author = identityService.loggedIdentity, + Locale locale = LocaleContextHolder.getLocale(), Map params = [:]) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title(title) + .authorId(author.activeActorId) + .params(params) + .build() + CreateCaseEventOutcome outcome = workflowService.createCase(createCaseParams) this.outcomes.add(outcome) return outcome.getCase() } - Task assignTask(String transitionId, Case aCase = useCase, IUser user = userService.loggedOrSystem, Map params = [:]) { + Case deleteCase(Case useCase) { + DeleteCaseEventOutcome outcome = workflowService.deleteCase(new DeleteCaseParams(useCase)) + return outcome.case + } + + Case deleteCase(String caseId) { + DeleteCaseEventOutcome outcome = workflowService.deleteCase(new DeleteCaseParams(caseId)) + return outcome.case + } + + /** + * todo javadoc + * */ + LoggedIdentity getLoggedOrSystem() { + // todo: release/8.0.0 system has no identity + LoggedIdentity identity = identityService.getLoggedIdentity() + return identity ?: identityService.getLoggedSystemIdentity() + } + + Task assignTask(String transitionId, Case aCase = useCase, LoggedIdentity assignee = identityService.loggedIdentity, + Map params = [:]) { String taskId = getTaskId(transitionId, aCase) - AssignTaskEventOutcome outcome = taskService.assignTask(user.transformToLoggedUser(), taskId, params) + TaskParams taskParams = TaskParams.with() + .taskId(taskId) + .assigneeId(assignee.activeActorId) + .params(params) + .build() + AssignTaskEventOutcome outcome = taskService.assignTask(taskParams) this.outcomes.add(outcome) updateCase() return outcome.getTask() } - Task assignTask(Task task, IUser user = userService.loggedOrSystem, Map params = [:]) { - return addTaskOutcomeAndReturnTask(taskService.assignTask(task, user, params)) + Task assignTask(Task task, LoggedIdentity assignee = identityService.loggedIdentity, Map params = [:]) { + TaskParams taskParams = TaskParams.with() + .task(task) + .assigneeId(assignee.activeActorId) + .params(params) + .build() + return addTaskOutcomeAndReturnTask(taskService.assignTask(taskParams)) } - void assignTasks(List tasks, IUser assignee = userService.loggedOrSystem, Map params = [:]) { - this.outcomes.addAll(taskService.assignTasks(tasks, assignee, params)) + void assignTasks(List tasks, LoggedIdentity assignee = identityService.loggedIdentity, Map params = [:]) { + this.outcomes.addAll(taskService.assignTasks(tasks, assignee.activeActorId, params)) } - Task cancelTask(String transitionId, Case aCase = useCase, IUser user = userService.loggedOrSystem, Map params = [:]) { + Task cancelTask(String transitionId, Case aCase = useCase, LoggedIdentity assignee = identityService.loggedIdentity, Map params = [:]) { String taskId = getTaskId(transitionId, aCase) - return addTaskOutcomeAndReturnTask(taskService.cancelTask(user.transformToLoggedUser(), taskId, params)) + TaskParams taskParams = TaskParams.with() + .taskId(taskId) + .assigneeId(assignee.activeActorId) + .params(params) + .build() + return addTaskOutcomeAndReturnTask(taskService.cancelTask(taskParams)) } - Task cancelTask(Task task, IUser user = userService.loggedOrSystem, Map params = [:]) { - return addTaskOutcomeAndReturnTask(taskService.cancelTask(task, user, params)) + Task cancelTask(Task task, LoggedIdentity assignee = identityService.loggedIdentity, Map params = [:]) { + TaskParams taskParams = TaskParams.with() + .task(task) + .assigneeId(assignee.activeActorId) + .params(params) + .build() + return addTaskOutcomeAndReturnTask(taskService.cancelTask(taskParams)) } - void cancelTasks(List tasks, IUser user = userService.loggedOrSystem, Map params = [:]) { - this.outcomes.addAll(taskService.cancelTasks(tasks, user, params)) + void cancelTasks(List tasks, LoggedIdentity assignee = identityService.loggedIdentity, Map params = [:]) { + this.outcomes.addAll(taskService.cancelTasks(tasks, assignee.activeActorId, params)) } private Task addTaskOutcomeAndReturnTask(TaskEventOutcome outcome) { @@ -754,17 +936,28 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { return outcome.getTask() } - void finishTask(String transitionId, Case aCase = useCase, IUser user = userService.loggedOrSystem, Map params = [:]) { + void finishTask(String transitionId, Case aCase = useCase, LoggedIdentity assignee = identityService.loggedIdentity, + Map params = [:]) { String taskId = getTaskId(transitionId, aCase) - addTaskOutcomeAndReturnTask(taskService.finishTask(user.transformToLoggedUser(), taskId, params)) + TaskParams taskParams = TaskParams.with() + .taskId(taskId) + .assigneeId(assignee.activeActorId) + .params(params) + .build() + addTaskOutcomeAndReturnTask(taskService.finishTask(taskParams)) } - void finishTask(Task task, IUser user = userService.loggedOrSystem, Map params = [:]) { - addTaskOutcomeAndReturnTask(taskService.finishTask(task, user, params)) + void finishTask(Task task, LoggedIdentity assignee = identityService.loggedIdentity, Map params = [:]) { + TaskParams taskParams = TaskParams.with() + .task(task) + .assigneeId(assignee.activeActorId) + .params(params) + .build() + addTaskOutcomeAndReturnTask(taskService.finishTask(taskParams)) } - void finishTasks(List tasks, IUser finisher = userService.loggedOrSystem, Map params = [:]) { - this.outcomes.addAll(taskService.finishTasks(tasks, finisher, params)) + void finishTasks(List tasks, LoggedIdentity assignee = identityService.loggedIdentity, Map params = [:]) { + this.outcomes.addAll(taskService.finishTasks(tasks, assignee.activeActorId, params)) } List findTasks(Closure predicate) { @@ -793,69 +986,73 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { refs.find { it.transitionId == transitionId }.stringId } - IUser assignRole(String roleMongoId, IUser user = userService.loggedUser) { - IUser actualUser = userService.addRole(user, roleMongoId) - return actualUser - } - - IUser assignRole(String roleId, String netId, IUser user = userService.loggedUser) { - List nets = petriNetService.getByIdentifier(netId) - nets.forEach({ net -> user = assignRole(roleId, net, user) }) - return user - } - - IUser assignRole(String roleId, PetriNet net, IUser user = userService.loggedUser) { - IUser actualUser = userService.addRole(user, net.roles.values().find { role -> role.importId == roleId }.stringId) - return actualUser - } - - IUser assignRole(String roleId, String netId, Version version, IUser user = userService.loggedUser) { - PetriNet net = petriNetService.getPetriNet(netId, version) - return assignRole(roleId, net, user) - } - - IUser removeRole(String roleMongoId, IUser user = userService.loggedUser) { - IUser actualUser = userService.removeRole(user, roleMongoId) - return actualUser + /** + * todo javadoc + * */ + Role assignRole(String roleId, String actorId = identityService.loggedIdentity.activeActorId , Map params = this.params) { + List roleAsList = assignRoles([roleId] as Set, actorId, params) + return roleAsList.isEmpty() ? null : roleAsList[0] } - IUser removeRole(String roleId, String netId, IUser user = userService.loggedUser) { - List nets = petriNetService.getByIdentifier(netId) - nets.forEach({ net -> user = removeRole(roleId, net, user) }) - return user + /** + * todo javadoc + * */ + List assignRoles(Set roleIds, String actorId = identityService.loggedIdentity.activeActorId, Map params = this.params) { + return roleService.assignRolesToActor(actorId, roleIds, params) } - IUser removeRole(String roleId, PetriNet net, IUser user = userService.loggedUser) { - IUser actualUser = userService.removeRole(user, net.roles.values().find { role -> role.importId == roleId }.stringId) - return actualUser + /** + * todo javadoc + * */ + Role removeRole(String roleId, String actorId = identityService.loggedIdentity.activeActorId, Map params = this.params) { + List roleAsList = removeRoles([roleId] as Set, actorId, params) + return roleAsList.isEmpty() ? null : roleAsList[0] } - IUser removeRole(String roleId, String netId, Version version, IUser user = userService.loggedUser) { - PetriNet net = petriNetService.getPetriNet(netId, version) - return removeRole(roleId, net, user) + /** + * todo javadoc + * */ + List removeRoles(Set roleIds, String actorId = identityService.loggedIdentity.activeActorId, Map params = this.params) { + return roleService.removeRolesFromActor(actorId, roleIds, params) } // TODO: release/8.0.0 merge check, params x dataset - SetDataEventOutcome setData(DataSet dataSet, IUser user = userService.loggedOrSystem) { - return addSetDataOutcomeToOutcomes(dataService.setData(useCase, dataSet, user)) + SetDataEventOutcome setData(DataSet dataSet, String actorId = identityService.loggedIdentity.activeActorId) { + return addSetDataOutcomeToOutcomes(dataService.setData(new SetDataParams(useCase, dataSet, actorId))) } - SetDataEventOutcome setData(Task task, DataSet dataSet, IUser user = userService.loggedOrSystem, Map params = [:]) { - return setData(task.stringId, dataSet, user, params) + SetDataEventOutcome setData(Task task, DataSet dataSet, String actorId = identityService.loggedIdentity.activeActorId, + Map params = [:]) { + return setData(task.stringId, dataSet, actorId, params) } - SetDataEventOutcome setData(String taskId, DataSet dataSet, IUser user = userService.loggedOrSystem, Map params = [:]) { - return addSetDataOutcomeToOutcomes(dataService.setData(taskId, dataSet, user, params)) + SetDataEventOutcome setData(String taskId, DataSet dataSet, String actorId = identityService.loggedIdentity.activeActorId, + Map params = [:]) { + SetDataParams setDataParams = SetDataParams.with() + .taskId(taskId) + .dataSet(dataSet) + .actorId(actorId) + .params(params) + .build() + return addSetDataOutcomeToOutcomes(dataService.setData(setDataParams)) } - SetDataEventOutcome setData(Transition transition, DataSet dataSet, IUser user = userService.loggedOrSystem, Map params = [:]) { - return addSetDataOutcomeToOutcomes(setData(transition.importId, this.useCase, dataSet, user, params)) + SetDataEventOutcome setData(Transition transition, DataSet dataSet, String actorId = identityService.loggedIdentity.activeActorId, + Map params = [:]) { + return addSetDataOutcomeToOutcomes(setData(transition.importId, this.useCase, dataSet, actorId, params)) } - SetDataEventOutcome setData(String transitionId, Case useCase, DataSet dataSet, IUser user = userService.loggedOrSystem, Map params = [:]) { + SetDataEventOutcome setData(String transitionId, Case useCase, DataSet dataSet, String actorId = identityService.loggedIdentity.activeActorId, + Map params = [:]) { def predicate = QTask.task.caseId.eq(useCase.stringId) & QTask.task.transitionId.eq(transitionId) def task = taskService.searchOne(predicate) - return addSetDataOutcomeToOutcomes(dataService.setData(task.stringId, dataSet, user, params)) + SetDataParams setDataParams = SetDataParams.with() + .task(task) + .dataSet(dataSet) + .actorId(actorId) + .params(params) + .build() + return addSetDataOutcomeToOutcomes(dataService.setData(setDataParams)) } @Deprecated @@ -881,28 +1078,48 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { return outcome } - Map getData(Task task, IUser user = userService.loggedOrSystem, Map params = [:]) { + Map getData(Task task, String actorId = identityService.loggedIdentity.activeActorId, Map params = [:]) { def useCase = workflowService.findOne(task.caseId) - return mapData(addGetDataOutcomeToOutcomesAndReturnData(dataService.getData(task, useCase, user, params))) + GetDataParams getDataParams = GetDataParams.with() + .task(task) + .useCase(useCase) + .actorId(actorId) + .params(params) + .build() + return mapData(addGetDataOutcomeToOutcomesAndReturnData(dataService.getData(getDataParams))) } - Map getData(String taskId, IUser user = userService.loggedOrSystem, Map params = [:]) { + Map getData(String taskId, String actorId = identityService.loggedIdentity.activeActorId, Map params = [:]) { Task task = taskService.findById(taskId) def useCase = workflowService.findOne(task.caseId) - return mapData(addGetDataOutcomeToOutcomesAndReturnData(dataService.getData(task, useCase, user, params))) + GetDataParams getDataParams = GetDataParams.with() + .task(task) + .useCase(useCase) + .actorId(actorId) + .params(params) + .build() + return mapData(addGetDataOutcomeToOutcomesAndReturnData(dataService.getData(getDataParams))) } - Map getData(Transition transition, IUser user = userService.loggedOrSystem, Map params = [:]) { - return getData(transition.stringId, this.useCase, user, params) + Map getData(Transition transition, String actorId = identityService.loggedIdentity.activeActorId, + Map params = [:]) { + return getData(transition.stringId, this.useCase, actorId, params) } - Map getData(String transitionId, Case useCase, IUser user = userService.loggedOrSystem, Map params = [:]) { + Map getData(String transitionId, Case useCase, String actorId = identityService.loggedIdentity.activeActorId, + Map params = [:]) { def predicate = QTask.task.caseId.eq(useCase.stringId) & QTask.task.transitionId.eq(transitionId) def task = taskService.searchOne(predicate) if (!task) { return new HashMap() } - return mapData(addGetDataOutcomeToOutcomesAndReturnData(dataService.getData(task, useCase, user, params))) + GetDataParams getDataParams = GetDataParams.with() + .task(task) + .useCase(useCase) + .actorId(actorId) + .params(params) + .build() + return mapData(addGetDataOutcomeToOutcomesAndReturnData(dataService.getData(getDataParams))) } private List addGetDataOutcomeToOutcomesAndReturnData(GetDataEventOutcome outcome) { @@ -917,8 +1134,8 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { } } - IUser loggedUser() { - return userService.loggedUser + LoggedIdentity loggedIdentity() { + return identityService.loggedIdentity } void saveFileToField(Case targetCase, String targetTransitionId, String targetFieldId, String filename, String storagePath = null) { @@ -953,139 +1170,65 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { mailService.sendMail(mailDraft) } - def changeUserByEmail(String email) { - [email : { cl -> - changeUserByEmail(email, "email", cl) - }, - name : { cl -> - changeUserByEmail(email, "name", cl) - }, - surname: { cl -> - changeUserByEmail(email, "surname", cl) - }, - tel : { cl -> - changeUserByEmail(email, "tel", cl) - }, - ] - } - - def changeUser(String id) { - [email : { cl -> - changeUser(id, "email", cl) - }, - name : { cl -> - changeUser(id, "name", cl) - }, - surname: { cl -> - changeUser(id, "surname", cl) - }, - tel : { cl -> - changeUser(id, "tel", cl) - }, - ] - } - - def changeUser(IUser user) { - [email : { cl -> - changeUser(user, "email", cl) - }, - name : { cl -> - changeUser(user, "name", cl) - }, - surname: { cl -> - changeUser(user, "surname", cl) - }, - tel : { cl -> - changeUser(user, "tel", cl) - }, - ] - } - - def changeUserByEmail(String email, String attribute, def cl) { - IUser user = userService.findByEmail(email) - changeUser(user, attribute, cl) + Identity changeIdentityByEmail(String email, IdentityParams identityParams) { + Optional identityOpt = identityService.findByUsername(email) + return changeIdentity(identityOpt, identityParams) } - def changeUser(String id, String attribute, def cl) { - IUser user = userService.findById(id) - changeUser(user, attribute, cl) + Identity changeIdentity(String id, IdentityParams identityParams) { + Optional identityOpt = identityService.findById(id) + return changeIdentity(identityOpt, identityParams) } - def changeUser(IUser user, String attribute, def cl) { - if (user == null) { - log.error("Cannot find user.") - return - } - - if (user.hasProperty(attribute) == null) { - log.error("User object does not have property [" + attribute + "]") - return + Identity changeIdentity(Optional identityOpt, IdentityParams identityParams) { + if (identityOpt.isEmpty()) { + log.error("Cannot find identity.") + return null } - user[attribute] = cl() as String - userService.save(user) + return identityService.update(identityOpt.get(), identityParams) } - MessageResource inviteUser(String email) { - NewUserRequest newUserRequest = new NewUserRequest() - newUserRequest.email = email - newUserRequest.groups = new HashSet<>() - newUserRequest.processRoles = new HashSet<>() - return inviteUser(newUserRequest) + MessageResource inviteIdentity(String email) { + NewIdentityRequest newIdentityRequest = new NewIdentityRequest() + newIdentityRequest.email = email + newIdentityRequest.groups = new HashSet<>() + newIdentityRequest.roles = new HashSet<>() + return inviteIdentity(newIdentityRequest) } - MessageResource inviteUser(NewUserRequest newUserRequest) { - IUser user = registrationService.createNewUser(newUserRequest) - if (user == null) + MessageResource inviteIdentity(NewIdentityRequest newIdentityRequest) { + Identity identity = registrationService.createNewIdentity(newIdentityRequest) + if (identity == null) return MessageResource.successMessage("Done") - mailService.sendRegistrationEmail(user) + mailService.sendRegistrationEmail(identity) - mailAttemptService.mailAttempt(newUserRequest.email) + mailAttemptService.mailAttempt(newIdentityRequest.email) return MessageResource.successMessage("Done") } - void deleteUser(String email) { - IUser user = userService.findByEmail(email) - if (user == null) - log.error("Cannot find user with email [" + email + "]") - deleteUser(user) - } - - void deleteUser(IUser user) { - List tasks = taskService.findByUser(new FullPageRequest(), user).toList() - if (tasks != null && tasks.size() > 0) - taskService.cancelTasks(tasks, user) - - QCase qCase = new QCase("case") - List cases = workflowService.searchAll(qCase.author.eq(user.transformToAuthor())).toList() - if (cases != null) - cases.forEach({ aCase -> aCase.setAuthor(Author.createAnonymizedAuthor()) }) - - userService.deleteUser(user) - } - - IUser findUserByEmail(String email) { - IUser user = userService.findByEmail(email) - if (user == null) { - log.error("Cannot find user with email [" + email + "]") + User findUserByEmail(String email) { + Optional userOpt = userService.findByEmail(email) + if (userOpt.isEmpty()) { + log.error("Cannot find user with email [{}]", email) return null } else { - return user + return userOpt.get() } } - IUser findUserById(String id) { - IUser user = userService.findById(id) - if (user == null) { - log.error("Cannot find user with id [" + id + "]") + User findUserById(String id) { + Optional userOpt = userService.findById(id) + if (userOpt.isEmpty()) { + log.error("Cannot find user with id [{}]", id) return null } else { - return user + return userOpt.get() } } - Validation validation(String rule, I18nString message) { - return new Validation(rule, message) + Validation validation(String name, Arguments clientArguments, Arguments serverArguments, I18nString message) { + return new Validation(name, clientArguments, serverArguments, message) } // TODO: release/8.0.0 remove? @@ -1127,22 +1270,22 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { } File exportCasesToFile(List requests, String pathName, ExportDataConfig config = null, - LoggedUser user = userService.loggedOrSystem.transformToLoggedUser(), + LoggedIdentity identity = identityService.loggedIdentity, int pageSize = exportConfiguration.getMongoPageSize(), Locale locale = LocaleContextHolder.getLocale(), Boolean isIntersection = false) { File exportFile = new File(pathName) - OutputStream out = exportCases(requests, exportFile, config, user, pageSize, locale, isIntersection) + OutputStream out = exportCases(requests, exportFile, config, identity, pageSize, locale, isIntersection) out.close() return exportFile } OutputStream exportCases(List requests, File outFile, ExportDataConfig config = null, - LoggedUser user = userService.loggedOrSystem.transformToLoggedUser(), + LoggedIdentity identity = identityService.loggedIdentity, int pageSize = exportConfiguration.getMongoPageSize(), Locale locale = LocaleContextHolder.getLocale(), Boolean isIntersection = false) { - return exportService.fillCsvCaseData(requests, outFile, config, user, pageSize, locale, isIntersection) + return exportService.fillCsvCaseData(requests, outFile, config, identity.activeActorId, pageSize, locale, isIntersection) } File exportTasksToFile(Closure predicate, String pathName, ExportDataConfig config = null) { @@ -1152,28 +1295,29 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { return exportFile } - OutputStream exportTasks(Closure predicate, File outFile, ExportDataConfig config = null, int pageSize = exportConfiguration.getMongoPageSize()) { + OutputStream exportTasks(Closure predicate, File outFile, ExportDataConfig config = null, + int pageSize = exportConfiguration.getMongoPageSize()) { QTask qTask = new QTask("task") return exportService.fillCsvTaskData(predicate(qTask), outFile, config, pageSize) } File exportTasksToFile(List requests, String pathName, ExportDataConfig config = null, - LoggedUser user = userService.loggedOrSystem.transformToLoggedUser(), + LoggedIdentity identity = identityService.loggedIdentity, int pageSize = exportConfiguration.getMongoPageSize(), Locale locale = LocaleContextHolder.getLocale(), Boolean isIntersection = false) { File exportFile = new File(pathName) - OutputStream out = exportTasks(requests, exportFile, config, user, pageSize, locale, isIntersection) + OutputStream out = exportTasks(requests, exportFile, config, identity, pageSize, locale, isIntersection) out.close() return exportFile } OutputStream exportTasks(List requests, File outFile, ExportDataConfig config = null, - LoggedUser user = userService.loggedOrSystem.transformToLoggedUser(), + LoggedIdentity identity = identityService.loggedIdentity, int pageSize = exportConfiguration.getMongoPageSize(), Locale locale = LocaleContextHolder.getLocale(), Boolean isIntersection = false) { - return exportService.fillCsvTaskData(requests, outFile, config, user, pageSize, locale, isIntersection) + return exportService.fillCsvTaskData(requests, outFile, config, identity.activeActorId, pageSize, locale, isIntersection) } FileFieldInputStream getFileFieldStream(Case useCase, Task task, FileField field, boolean forPreview = false) { @@ -1193,6 +1337,7 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { } /** + * todo javadoc * Action API case search function using Elasticsearch database * @param requests the CaseSearchRequest list * @param loggedUser the user who is searching for the requests @@ -1202,9 +1347,9 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { * @param isIntersection to decide null query handling * @return page of cases * */ - Page findCasesElastic(List requests, LoggedUser loggedUser = userService.loggedOrSystem.transformToLoggedUser(), + Page findCasesElastic(List requests, LoggedIdentity identity = identityService.loggedIdentity, int page = 1, int pageSize = 25, Locale locale = Locale.default, boolean isIntersection = false) { - return elasticCaseService.search(requests, loggedUser, PageRequest.of(page, pageSize), locale, isIntersection) + return elasticCaseService.search(requests, identity, PageRequest.of(page, pageSize), locale, isIntersection) } /** @@ -1217,10 +1362,10 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { * @param isIntersection to decide null query handling * @return page of cases * */ - Page findCasesElastic(Map request, LoggedUser loggedUser = userService.loggedOrSystem.transformToLoggedUser(), + Page findCasesElastic(Map request, LoggedIdentity identity = identityService.loggedIdentity, int page = 1, int pageSize = 25, Locale locale = Locale.default, boolean isIntersection = false) { List requests = Collections.singletonList(new CaseSearchRequest(request)) - return findCasesElastic(requests, loggedUser, page, pageSize, locale, isIntersection) + return findCasesElastic(requests, identity, page, pageSize, locale, isIntersection) } /** @@ -1233,9 +1378,9 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { * @param isIntersection to decide null query handling * @return page of cases * */ - Page findTasks(List requests, LoggedUser loggedUser = userService.loggedOrSystem.transformToLoggedUser(), + Page findTasks(List requests, LoggedIdentity identity = identityService.loggedIdentity, int page = 1, int pageSize = 25, Locale locale = Locale.default, boolean isIntersection = false) { - return elasticTaskService.search(requests, loggedUser, PageRequest.of(page, pageSize), locale, isIntersection) + return elasticTaskService.search(requests, identity, PageRequest.of(page, pageSize), locale, isIntersection) } /** @@ -1248,17 +1393,17 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { * @param isIntersection to decide null query handling * @return page of cases * */ - Page findTasks(Map request, LoggedUser loggedUser = userService.loggedOrSystem.transformToLoggedUser(), + Page findTasks(Map request, LoggedIdentity identity = identityService.loggedIdentity, int page = 1, int pageSize = 25, Locale locale = Locale.default, boolean isIntersection = false) { List requests = Collections.singletonList(new ElasticTaskSearchRequest(request)) - return findTasks(requests, loggedUser, page, pageSize, locale, isIntersection) + return findTasks(requests, identity, page, pageSize, locale, isIntersection) } List findDefaultFilters() { if (!createDefaultFilters) { return [] } - return findCases({ it.processIdentifier.eq(FilterRunner.FILTER_PETRI_NET_IDENTIFIER).and(it.author.id.eq(userService.system.stringId)) }) + return findCases({ it.processIdentifier.eq(FilterRunner.FILTER_PETRI_NET_IDENTIFIER).and(it.author.getStringId.eq(userService.getSystemUser().stringId)) }) } /** @@ -1413,67 +1558,10 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { * @return */ def deleteFilter(Case filter) { - workflowService.deleteCase(filter.stringId) - } - - /** - * create menu item for given filter instance - * @param uri - * @param identifier - unique item identifier - * @param filter - * @param groupName - * @param allowedRoles ["role_import_id": "net_import_id"] - * @param bannedRoles ["role_import_id": "net_import_id"] - * @return - */ - @Deprecated - // TODO: release/8.0.0 check merge changes in all menu item functions - Case createMenuItem(String uri, String identifier, Case filter, String groupName, Map allowedRoles, Map bannedRoles = [:], List defaultHeaders = []) { - return doCreateMenuItem(uri, identifier, filter, nextGroupService.findByName(groupName), collectRolesForPreferenceItem(allowedRoles), collectRolesForPreferenceItem(bannedRoles), defaultHeaders) - } - - /** - * create menu item for given filter instance - * @param uri - * @param identifier - unique item identifier - * @param filter - * @param groupName - * @param allowedRoles - * @param bannedRoles - * @return - */ - Case createMenuItem(String uri, String identifier, Case filter, String groupName, List allowedRoles, List bannedRoles = [], List defaultHeaders = []) { - return doCreateMenuItem(uri, identifier, filter, nextGroupService.findByName(groupName), collectRolesForPreferenceItem(allowedRoles), collectRolesForPreferenceItem(bannedRoles), defaultHeaders) - } - - /** - * create menu item for given filter instance - * @param uri - * @param identifier - unique item identifier - * @param filter - * @param groupName - * @param allowedRoles ["role_import_id": "net_import_id"] - * @param bannedRoles ["role_import_id": "net_import_id"] - * @param group - if null, default group is used - * @param group - if null, default group is used - * @return - */ - Case createMenuItem(String uri, String identifier, Case filter, Map allowedRoles, Map bannedRoles = [:], Case group = null, List defaultHeaders = []) { - return doCreateMenuItem(uri, identifier, filter, group, collectRolesForPreferenceItem(allowedRoles), collectRolesForPreferenceItem(bannedRoles), defaultHeaders) - } - - /** - * create menu item for given filter instance - * @param uri - * @param identifier - unique item identifier - * @param filter - * @param allowedRoles - * @param bannedRoles - * @param group - if null, default group is used - * @return - */ - Case createMenuItem(String uri, String identifier, Case filter, List allowedRoles, List bannedRoles = [], Case group = null, List defaultHeaders = []) { - return doCreateMenuItem(uri, identifier, filter, group, collectRolesForPreferenceItem(allowedRoles), collectRolesForPreferenceItem(bannedRoles), defaultHeaders) + DeleteCaseParams deleteCaseParams = DeleteCaseParams.with() + .useCase(filter) + .build() + workflowService.deleteCase(deleteCaseParams) } /** @@ -1717,11 +1805,7 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { item = workflowService.findOne(item.stringId) def roles = cl() MultichoiceMapField dataField = item.dataSet.get(roleFieldId) as MultichoiceMapField - if (roles instanceof List) { - dataField.options = collectRolesForPreferenceItem(roles) - } else if (roles instanceof Map) { - dataField.options = collectRolesForPreferenceItem(roles) - } + dataField.options = collectRolesForPreferenceItem(roles) workflowService.save(item) } @@ -1732,39 +1816,13 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { */ def deleteMenuItem(Case item) { async.run { - workflowService.deleteCase(item.stringId) + DeleteCaseParams deleteCaseParams = DeleteCaseParams.with() + .useCase(item) + .build() + workflowService.deleteCase(deleteCaseParams) } } - /** - * simplifies the process of creating a filter, menu item - * @param uri - * @param identifier - unique identifier of menu item - * @param title - * @param query - * @param icon - * @param type - "Case" or "Task" - * @param allowedNets - * @param groupName - name of group to add menu item to - * @param allowedRoles - * @param bannedRoles - * @param visibility - "private" or "public" - * @return - */ - @Deprecated - Case createFilterInMenu(String uri, String identifier, def title, String query, String type, - List allowedNets, - String groupName, - Map allowedRoles = [:], - Map bannedRoles = [:], - List defaultHeaders = [], - String icon = "", - String visibility = DefaultFiltersRunner.FILTER_VISIBILITY_PRIVATE) { - Case filter = createFilter(title, query, type, allowedNets, icon, visibility, null) - Case menuItem = createMenuItem(uri, identifier, filter, groupName, allowedRoles, bannedRoles, defaultHeaders) - return menuItem - } - /** * simplifies the process of creating a filter, menu item * @param uri @@ -1782,8 +1840,8 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { */ @Deprecated Case createFilterInMenu(String uri, String identifier, def title, String query, String type, List allowedNets, - Map allowedRoles = [:], - Map bannedRoles = [:], + List allowedRoles = [], + List bannedRoles = [], List defaultHeaders, String icon = "", String visibility = DefaultFiltersRunner.FILTER_VISIBILITY_PRIVATE, @@ -1793,27 +1851,33 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { return menuItem } - protected Case doCreateMenuItem(String uri, String identifier, Case filter, Case orgGroup, Map allowedRoles, Map bannedRoles, List defaultHeaders) { - if (findMenuItem(identifier)) { - throw new IllegalArgumentException("Menu item identifier $identifier is not unique!") + Case createMenuItem(MenuItemBody body) { + String sanitizedIdentifier = sanitize(body.identifier) + + if (existsMenuItem(sanitizedIdentifier)) { + throw new IllegalArgumentException("Menu item identifier $sanitizedIdentifier is not unique!") } - orgGroup = orgGroup ?: nextGroupService.findDefaultGroup() - Case itemCase = createCase(FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER, filter.title) - itemCase.setUriNodeId(uriService.findByUri(uri).id.toString()) - (itemCase.dataSet.get(PREFERENCE_ITEM_FIELD_ALLOWED_ROLES) as MultichoiceMapField).options = allowedRoles - (itemCase.dataSet.get(PREFERENCE_ITEM_FIELD_BANNED_ROLES) as MultichoiceMapField).options = bannedRoles - itemCase = workflowService.save(itemCase) - // TODO: release/8.0.0 decouple - Task newItemTask = findTask(itemCase.getTaskStringId("initialize")) - assignTask(newItemTask) - setData(newItemTask, new DataSet([ - (PREFERENCE_ITEM_FIELD_FILTER_CASE) : new CaseField(rawValue: [filter.stringId]), - (PREFERENCE_ITEM_FIELD_PARENT_ID) : new TextField(rawValue: orgGroup.stringId), - (PREFERENCE_ITEM_FIELD_DEFAULT_HEADERS): new TextField(rawValue: defaultHeaders.join(',')), - (PREFERENCE_ITEM_FIELD_IDENTIFIER) : new TextField(rawValue: identifier) - ])) + + Case parentItemCase = getOrCreateFolderItem(body.uri) + I18nString newName = body.menuName ?: (body.filter?.dataSet[FILTER_FIELD_I18N_FILTER_NAME].value as I18nString) + + Case menuItemCase = createCase(FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER, newName?.defaultValue) + menuItemCase.setUriNodeId(uriService.findByUri(body.uri).stringId) + menuItemCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_ALLOWED_ROLES.attributeId].options = body.allowedRoles + menuItemCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_BANNED_ROLES.attributeId].options = body.bannedRoles + if (parentItemCase != null) { + parentItemCase = appendChildCaseIdAndSave(parentItemCase, menuItemCase.stringId) + } + menuItemCase = workflowService.save(menuItemCase) + Task newItemTask = findTask { it.id.eq(new ObjectId(menuItemCase.getTaskStringId(MenuItemConstants.PREFERENCE_ITEM_FIELD_INIT_TRANS_ID.attributeId))) } + String nodePath = createNodePath(body.uri, sanitizedIdentifier) + uriService.getOrCreate(nodePath, UriContentType.CASE) + + newItemTask = assignTask(newItemTask) + setData(newItemTask, body.toDataSet(parentItemCase.stringId, nodePath)) finishTask(newItemTask) - return workflowService.findOne(itemCase.stringId) + + return workflowService.findOne(menuItemCase.stringId) } private Case appendChildCaseId(Case folderCase, String childItemCaseId) { @@ -1946,14 +2010,14 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { List findCasesElastic(String query, Pageable pageable) { CaseSearchRequest request = new CaseSearchRequest() request.query = query - List result = elasticCaseService.search([request], userService.system.transformToLoggedUser(), pageable, LocaleContextHolder.locale, false).content + List result = elasticCaseService.search([request], identityService.getLoggedIdentity().activeActorId, pageable, LocaleContextHolder.locale, false).content return result } long countCasesElastic(String query) { CaseSearchRequest request = new CaseSearchRequest() request.query = query - return elasticCaseService.count([request], userService.system.transformToLoggedUser(), LocaleContextHolder.locale, false) + return elasticCaseService.count([request], identityService.getLoggedIdentity().activeActorId, LocaleContextHolder.locale, false) } @Deprecated @@ -1961,23 +2025,11 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { return findMenuItem(uri, name) } - private Map collectRolesForPreferenceItem(List roles) { + private Map collectRolesForPreferenceItem(List roleImportIds) { + List roles = roleService.findAllProcessRolesByImportIds(roleImportIds as Set) return roles.collectEntries { role -> - PetriNet net = petriNetService.get(new ObjectId(role.netId)) - return [(role.importId + ":" + net.identifier), ("$role.name ($net.title)" as String)] - } as Map - } - - private Map collectRolesForPreferenceItem(Map roles) { - Map temp = [:] - return roles.collectEntries { entry -> - if (!temp.containsKey(entry.value)) { - temp.put(entry.value, petriNetService.getNewestVersionByIdentifier(entry.value)) - } - PetriNet net = temp[entry.value] - ProcessRole role = net.roles.find { it.value.importId == entry.key }.value - return [(role.importId + ":" + net.identifier), ("$role.name ($net.title)" as String)] - } as Map + return [(role.importId), role.title] + } } private void updateFilter(Case filter, DataSet dataSet) { @@ -1993,11 +2045,10 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { return } useCase = workflowService.findOne(useCase.stringId) - initFieldsMap(action.fieldIds, useCase) } @Deprecated - Map createMenuItem(String id, String uri, String query, String icon, String title, List allowedNets, Map roles, Map bannedRoles = [:], Case group = null, List defaultHeaders = []) { + Map createMenuItem(String id, String uri, String query, String icon, String title, List allowedNets, List roles, List bannedRoles = [], Case group = null, List defaultHeaders = []) { if (existsMenuItem(id)) { log.info("$id menu exists") return null @@ -2078,7 +2129,7 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { * @return created or updated menu item instance * */ Case createOrUpdateMenuItem(String uri, String identifier, I18nString name, String icon = "filter_none", Case filter = null, - Map allowedRoles = [:], Map bannedRoles = [:], + List allowedRoles = [], List bannedRoles = [], List caseDefaultHeaders = [], List taskDefaultHeaders = []) { MenuItemBody body = new MenuItemBody(uri, identifier, name, icon) body.setAllowedRoles(collectRolesForPreferenceItem(allowedRoles)) @@ -2117,8 +2168,8 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { * */ Case createOrUpdateMenuItemAndFilter(String uri, String itemIdentifier, I18nString itemAndFilterName, String filterQuery, String filterType, String filterVisibility, List filterAllowedNets = [], - String itemAndFilterIcon = "filter_none", Map itemAllowedRoles = [:], - Map itemBannedRoles = [:], List itemCaseDefaultHeaders = [], + String itemAndFilterIcon = "filter_none", List itemAllowedRoles = [], + List itemBannedRoles = [], List itemCaseDefaultHeaders = [], List itemTaskDefaultHeaders = [], def filterMetadata = null) { MenuItemBody body = new MenuItemBody(uri, itemIdentifier, itemAndFilterName, itemAndFilterIcon) body.allowedRoles = collectRolesForPreferenceItem(itemAllowedRoles) @@ -2312,13 +2363,12 @@ class ActionDelegate /*TODO: release/8.0.0: implements ActionAPI*/ { } node = uriService.findByUri(uncheckedUri) } - return node.uriPath } Field getFieldOfTask(String taskId, String fieldId) { Task task = taskService.findOne(taskId) Case taskCase = workflowService.findOne(task.caseId) - return taskCase.getPetriNet().getDataSet().get(fieldId) + return taskCase.getProcess().getDataSet().get(fieldId) } } \ No newline at end of file diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionRunner.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionRunner.groovy index 6c6aea0f0cc..273f6aba09c 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionRunner.groovy @@ -2,15 +2,19 @@ package com.netgrif.application.engine.petrinet.domain.dataset.logic.action import com.netgrif.application.engine.petrinet.domain.Function +import com.netgrif.application.engine.petrinet.domain.Transition import com.netgrif.application.engine.petrinet.domain.dataset.Field +import com.netgrif.application.engine.transaction.NaeTransaction import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.Task -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome import com.netgrif.application.engine.workflow.service.interfaces.IFieldActionsCacheService import groovy.util.logging.Slf4j import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Lookup +import org.springframework.data.mongodb.MongoTransactionManager import org.springframework.stereotype.Component +import org.springframework.transaction.support.TransactionSynchronizationManager @Slf4j @Component @@ -23,9 +27,12 @@ abstract class ActionRunner { @Autowired private IFieldActionsCacheService actionsCacheService + @Autowired + private MongoTransactionManager transactionManager + private Map actionsCache = new HashMap<>() - List run(Action action, Case useCase, Map params, List functions = []) { + List run(Action action, Case useCase, Map params, List functions = []) { return run(action, useCase, Optional.empty(), null, params, functions) } @@ -34,10 +41,19 @@ abstract class ActionRunner { actionsCache = new HashMap<>() } log.debug("Action: $action") - def code = getActionCode(action, functions) + def code = getActionCode(action, functions, useCase) try { code.init(action, useCase, task, changes, this, params) - code() + if (TransactionSynchronizationManager.isSynchronizationActive()) { + def transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(code) + .build() + transaction.setForceCreation(false) + transaction.begin() + } else { + code() + } } catch (Exception e) { log.error("Action: $action.definition") throw e @@ -45,11 +61,11 @@ abstract class ActionRunner { return ((ActionDelegate) code.delegate).outcomes } - Closure getActionCode(Action action, List functions, boolean shouldRewriteCachedActions = false) { - return getActionCode(actionsCacheService.getCompiledAction(action, shouldRewriteCachedActions), functions) + Closure getActionCode(Action action, List functions, Case useCase, boolean shouldRewriteCachedActions = false) { + return getActionCode(actionsCacheService.getCompiledAction(action, shouldRewriteCachedActions), functions, useCase) } - Closure getActionCode(Closure code, List functions) { + Closure getActionCode(Closure code, List functions, Case useCase) { def actionDelegate = getActionDelegate() actionsCacheService.getCachedFunctions(functions).each { @@ -62,6 +78,14 @@ abstract class ActionRunner { } actionDelegate.metaClass."${entry.key}" = namespace } + if (useCase != null) { + useCase.dataSet.fields.forEach { String id, Field field -> + actionDelegate.metaClass."$id" = field + } + useCase.process.transitions.forEach { String id, Transition t -> + actionDelegate.metaClass."$id" = t + } + } return code.rehydrate(actionDelegate, code.owner, code.thisObject) } diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ExpressionDelegate.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ExpressionDelegate.groovy index ef115cd997c..3c0e2672358 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ExpressionDelegate.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ExpressionDelegate.groovy @@ -1,13 +1,9 @@ package com.netgrif.application.engine.petrinet.domain.dataset.logic.action -import com.netgrif.application.engine.auth.service.interfaces.IUserService import groovy.util.logging.Slf4j -import org.springframework.beans.factory.annotation.Autowired @Slf4j class ExpressionDelegate { // TODO: release/8.0.0 services and methods? - @Autowired - IUserService userService } diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ExpressionRunner.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ExpressionRunner.groovy index 9bff66bd585..65f3160ac81 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ExpressionRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ExpressionRunner.groovy @@ -1,5 +1,7 @@ package com.netgrif.application.engine.petrinet.domain.dataset.logic.action +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authorization.service.interfaces.IUserService import com.netgrif.application.engine.elastic.service.executors.MaxSizeHashMap import com.netgrif.application.engine.event.IGroovyShellFactory import com.netgrif.application.engine.petrinet.domain.dataset.Field @@ -9,6 +11,7 @@ import groovy.util.logging.Slf4j import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Lookup import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Lazy import org.springframework.stereotype.Component @Slf4j @@ -21,10 +24,16 @@ abstract class ExpressionRunner { @Lookup("actionDelegate") abstract ActionDelegate getExpressionDelegate() - @Autowired private IGroovyShellFactory shellFactory + @Lazy + @Autowired + private IIdentityService identityService + + @Autowired + private IUserService userService + private Map cache @Autowired @@ -32,15 +41,14 @@ abstract class ExpressionRunner { cache = new MaxSizeHashMap<>(cacheSize) } - // TODO: release/8.0.0 fields? Map fields - def run(Case useCase, Expression expression, Map params = [:]) { + T run(Expression expression, Case useCase = null, Field field = null, Map params = [:]) { log.debug("Expression: $expression") def code = getExpressionCode(expression) try { - initCode(code.delegate, useCase, params) - code() + initCode(code.delegate, useCase, field, params) + return code() as T } catch (Exception e) { - log.error("Action: $expression.definition") + log.error("Expression evaluation failed: $expression.definition") throw e } } @@ -56,11 +64,17 @@ abstract class ExpressionRunner { return code.rehydrate(getExpressionDelegate(), code.owner, code.thisObject) } - protected void initCode(def delegate, Case useCase, Map params) { - delegate.metaClass.useCase = useCase - delegate.metaClass.params = params - useCase.dataSet.fields.values().forEach { Field field -> - delegate.metaClass."$field.importId" = field + protected void initCode(def delegate, Case useCase, Field field, Map params) { + if (useCase != null) { + delegate.metaClass.useCase = useCase + useCase.dataSet.fields.values().forEach { Field f -> + delegate.metaClass."$f.importId" = f + } } + delegate.metaClass.params = params + delegate.metaClass.field = field + // TODO: release/8.0.0 + delegate.metaClass.loggedUser = identityService.loggedIdentity + delegate.metaClass.systemUser = userService.systemUser } } diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/FrontendActionOutcome.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/FrontendActionOutcome.groovy index dc644ec4073..9ff4a063b1e 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/FrontendActionOutcome.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/FrontendActionOutcome.groovy @@ -2,8 +2,8 @@ package com.netgrif.application.engine.petrinet.domain.dataset.logic.action import com.netgrif.application.engine.petrinet.domain.dataset.logic.FrontAction import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.Task -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome class FrontendActionOutcome { diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ValidationDelegate.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ValidationDelegate.groovy new file mode 100644 index 00000000000..ef85a65518e --- /dev/null +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ValidationDelegate.groovy @@ -0,0 +1,167 @@ +package com.netgrif.application.engine.petrinet.domain.dataset.logic.action + + +import com.netgrif.application.engine.petrinet.domain.dataset.* +import groovy.util.logging.Slf4j + +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter +import java.time.format.DateTimeParseException + +@Slf4j +class ValidationDelegate { + + public static final String FUTURE = 'future' + public static final String TODAY = 'today' + public static final String PAST = 'past' + public static final String NOW = 'now' + public static final String INF = 'inf' + public static final String TEL_NUMBER_REGEX = '^(?:\\+?(\\d{1,3}))?([-. (]*(\\d{3})[-. )]*)?((\\d{3})[-. ]*(\\d{2,4})(?:[-.x ]*(\\d+))?)$' + public static final String EMAIL_REGEX = '^[a-zA-Z0-9\\._\\%\\+\\-]+@[a-zA-Z0-9\\.\\-]+\\.[a-zA-Z]{2,}$' + + // todo NAE-1788: thisField keyword + Field field + + Boolean isNotEmpty() { + return field.rawValue != null + } + + // boolean field validations + Boolean requiredTrue() { + return field instanceof BooleanField && isNotEmpty() && field.rawValue == true + } + + // date field validations + Boolean between(def from, def to) { + if (!(field instanceof DateField || field instanceof DateTimeField) || !isNotEmpty()) { + return false + } + + LocalDateTime updateDate_TODAY = field instanceof DateField ? LocalDate.now().atStartOfDay() : LocalDateTime.now() + LocalDateTime thisFieldValue = field.rawValue instanceof LocalDateTime ? field.rawValue : (field.rawValue as LocalDate).atStartOfDay() + + def fromDate = from + if (from instanceof String) { + LocalDate parsedDate = parseStringToLocalDate(from) + fromDate = parsedDate ? parsedDate.atStartOfDay() : from + } + + def toDate = to + if (to instanceof String) { + LocalDate parsedDate = parseStringToLocalDate(to) + toDate = parsedDate ? parsedDate.atStartOfDay() : to + } + + if ((fromDate == TODAY || fromDate == NOW) && toDate == FUTURE) { + if (thisFieldValue < updateDate_TODAY) { + return false + } + } else if (fromDate == PAST && (toDate == TODAY || toDate == NOW)) { + if (thisFieldValue > updateDate_TODAY) { + return false + } + } else if (fromDate == PAST && (toDate instanceof LocalDateTime)) { + if (thisFieldValue > toDate) { + return false + } + } else if (fromDate == TODAY && (toDate instanceof LocalDateTime)) { + if (thisFieldValue > toDate || thisFieldValue < updateDate_TODAY) { + return false + } + } else if ((fromDate instanceof LocalDateTime) && toDate == TODAY) { + if (thisFieldValue < fromDate || thisFieldValue > updateDate_TODAY) { + return false + } + } else if (toDate == FUTURE && (fromDate instanceof LocalDateTime)) { + if (thisFieldValue < fromDate) { + return false + } + } else if ((fromDate instanceof LocalDateTime) && (toDate instanceof LocalDateTime)) { + if (thisFieldValue > toDate || thisFieldValue < fromDate) { + return false + } + } + return true + } + + Boolean workday() { + return (field instanceof DateField || field instanceof DateTimeField) && isNotEmpty() && !field.rawValue.dayOfWeek.isWeekend() + } + + Boolean weekend() { + return (field instanceof DateField || field instanceof DateTimeField) && isNotEmpty() && field.rawValue.dayOfWeek.isWeekend() + } + + protected static LocalDate parseStringToLocalDate(String stringDate) { + if (stringDate == null) { + return null + } + List patterns = Arrays.asList("dd.MM.yyyy", "") + try { + return LocalDate.parse(stringDate, DateTimeFormatter.BASIC_ISO_DATE) + } catch (DateTimeParseException ignored) { + try { + return LocalDate.parse(stringDate, DateTimeFormatter.ISO_DATE) + } catch (DateTimeParseException ignored2) { + for (String pattern : patterns) { + try { + return LocalDateTime.parse(stringDate, DateTimeFormatter.ofPattern(pattern)) + } catch (DateTimeParseException | IllegalArgumentException ignored3) { + } + } + } + } + return null + } + + // number field validations + Boolean odd() { + return field instanceof NumberField && isNotEmpty() && field.rawValue as Double % 2 != 0 + } + + Boolean even() { + return field instanceof NumberField && isNotEmpty() && field.rawValue as Double % 2 == 0 + } + + Boolean positive() { + return field instanceof NumberField && isNotEmpty() && field.rawValue >= 0 + } + + Boolean negative() { + return field instanceof NumberField && isNotEmpty() && field.rawValue <= 0 + } + + Boolean decimal() { + return field instanceof NumberField && isNotEmpty() && field.rawValue as Double % 1 == 0 + } + + Boolean inrange(def from, def to) { + if (from instanceof String && from.toLowerCase() == INF) { + from = Double.MIN_VALUE + } + if (to instanceof String && to.toLowerCase() == INF) { + to = Double.MAX_VALUE + } + return field instanceof NumberField && isNotEmpty() && field.rawValue >= from as Double && field.rawValue <= to as Double + } + + // text field validations + Boolean regex(String pattern) { + return field instanceof TextField && isNotEmpty() && field.rawValue ==~ pattern + } + + Boolean minlength(Integer minLength) { + return field instanceof TextField && isNotEmpty() && (field.rawValue as String).length() >= minLength + } + + Boolean maxlength(Integer maxLength) { + return field instanceof TextField && isNotEmpty() && (field.rawValue as String).length() <= maxLength + } + + Boolean telnumber() { return regex(TEL_NUMBER_REGEX) } + + Boolean email() { + return regex(EMAIL_REGEX) + } +} diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ValidationExecutioner.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ValidationExecutioner.groovy new file mode 100644 index 00000000000..80796e1342a --- /dev/null +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ValidationExecutioner.groovy @@ -0,0 +1,92 @@ +package com.netgrif.application.engine.petrinet.domain.dataset.logic.action + +import com.netgrif.application.engine.event.IGroovyShellFactory +import com.netgrif.application.engine.petrinet.domain.dataset.Field +import com.netgrif.application.engine.petrinet.domain.dataset.Validation +import com.netgrif.application.engine.validations.ValidationRegistry +import com.netgrif.application.engine.workflow.domain.Case +import groovy.util.logging.Slf4j +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Lookup +import org.springframework.stereotype.Component + +@Slf4j +@Component +abstract class ValidationExecutioner { + + @Lookup("validationDelegate") + abstract ValidationDelegate getValidationDelegate() + + @Autowired + private ValidationRegistry registry; + + @Autowired + private IGroovyShellFactory shellFactory + + void execute(Case useCase, Field field) { + List validations = field.getValidations() + if (!validations) { + return + } + + log.info("Validations: ${validations.collect { it.name }}") + + ValidationDelegate delegate = initDelegate(useCase, field, validations.collect { it.name }) + // TODO: release/8.0.0 required fields, null raw value + validations.each { validation -> + runValidation(validation, delegate) + } + } + + protected void runValidation(Validation validation, ValidationDelegate delegate) { + Closure code = initCode(validation, delegate) + if (!code()) { + throw new IllegalArgumentException(validation.message.toString()) + } + } + + protected Closure getValidationCode(String validationName) { + return this.registry.getValidation(validationName) + } + + protected static String escapeSpecialCharacters(String s) { + return s.replace('\\', '\\\\') + .replace('\'', '\\\'') + } + + protected Closure initCode(Validation validation, ValidationDelegate delegate) { + List argumentList = [] + if (validation.serverArguments != null) { + argumentList = validation.serverArguments.argument.collect { it.isDynamic() ? it.definition : "'${escapeSpecialCharacters(it.defaultValue)}'" } + } + String validationCall = "${validation.name}(${argumentList.join(", ")})" + Closure code = this.shellFactory.getGroovyShell().evaluate("{ -> return " + validationCall + " }") as Closure + return code.rehydrate(delegate, code.owner, code.thisObject) + } + + protected ValidationDelegate initDelegate(Case useCase, Field thisField, List validationNames) { + ValidationDelegate delegate = getValidationDelegate() + delegate.metaClass.useCase = useCase + useCase.dataSet.fields.values().forEach { Field field -> + delegate.metaClass."$field.importId" = field + } + + validationNames = filterConflictedValidationNames(useCase, validationNames) + validationNames.each { validationName -> + delegate.metaClass."$validationName" = getValidationCode(validationName) + } + + delegate.field = thisField + return delegate + } + + private static List filterConflictedValidationNames(Case useCase, List validationNames) { + List fieldNames = useCase.dataSet.fields.keySet() as List + fieldNames.retainAll(validationNames) + if (!fieldNames.isEmpty()) { + log.warn("Ignoring validations {} for case [{}]: field names are identical with validation names", fieldNames, useCase.stringId) + validationNames -= fieldNames + } + return validationNames + } +} diff --git a/src/main/groovy/com/netgrif/application/engine/startup/AllDataTransitionRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/AllDataTransitionRunner.groovy index cd1e49abdd0..238ec37ae69 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/AllDataTransitionRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/AllDataTransitionRunner.groovy @@ -1,8 +1,12 @@ package com.netgrif.application.engine.startup -import com.netgrif.application.engine.importer.model.Document +import com.netgrif.application.engine.importer.model.Process import com.netgrif.application.engine.importer.model.Transition import com.netgrif.application.engine.importer.service.AllDataConfiguration + +//import com.netgrif.application.engine.importer.model.Document +//import com.netgrif.application.engine.importer.model.Transition + import com.netgrif.application.engine.importer.service.Importer import groovy.transform.CompileStatic import groovy.util.logging.Slf4j @@ -38,8 +42,7 @@ class AllDataTransitionRunner extends AbstractOrderedCommandLineRunner { return } InputStream netStream = configurationFile.inputStream - Document document = getImporter().unmarshallXml(netStream) - + Process document = getImporter().unmarshallXml(netStream) Transition allData = document.getTransition().first() configuration.allData = allData diff --git a/src/main/groovy/com/netgrif/application/engine/startup/AnonymousIdentityRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/AnonymousIdentityRunner.groovy new file mode 100644 index 00000000000..8767ef960e0 --- /dev/null +++ b/src/main/groovy/com/netgrif/application/engine/startup/AnonymousIdentityRunner.groovy @@ -0,0 +1,59 @@ +package com.netgrif.application.engine.startup + +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.constants.AnonymIdentityConstants +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService +import com.netgrif.application.engine.authorization.service.interfaces.IUserService +import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import groovy.transform.CompileStatic +import groovy.util.logging.Slf4j +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Component + +@Slf4j +@Component +@CompileStatic +class AnonymousIdentityRunner extends AbstractOrderedCommandLineRunner { + + @Autowired + private IUserService userService + + @Autowired + private IIdentityService identityService + + @Autowired + private IRoleService roleService + + static final String anonymousFlag = "anonymous" + + @Override + void run(String... args) throws Exception { + Optional anonymOpt = identityService.findByUsername(AnonymIdentityConstants.defaultUsername()) + if (anonymOpt.isPresent()) { + return + } + createAnonymousIdentityWithUser() + } + + private void createAnonymousIdentityWithUser() { + Identity anonymIdentity = identityService.createWithDefaultUser(IdentityParams.with() + .username(new TextField(AnonymIdentityConstants.defaultUsername())) + .password(new TextField("n/a")) + .firstname(new TextField(AnonymIdentityConstants.FIRSTNAME)) + .lastname(new TextField(AnonymIdentityConstants.LASTNAME)) + .properties(Map.of(anonymousFlag, "true")) + .build()) + + Set roleIds = Set.of(roleService.findApplicationRoleByImportId(ApplicationRoleRunner.ANONYMOUS_APP_ROLE).getStringId(), + roleService.findAnonymousRole().getStringId()); + roleService.assignRolesToActor(anonymIdentity.getMainActorId(), roleIds); + + Set keywords = Set.of(AnonymIdentityConstants.defaultUsername()) + userService.registerForbiddenKeywords(keywords) + identityService.registerForbiddenKeywords(keywords) + + log.info("Created anonymous identity [{}] with user [{}].", anonymIdentity.stringId, anonymIdentity.mainActorId) + } +} diff --git a/src/main/groovy/com/netgrif/application/engine/startup/AnonymousRoleRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/AnonymousRoleRunner.groovy deleted file mode 100644 index 0671bc11a17..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/startup/AnonymousRoleRunner.groovy +++ /dev/null @@ -1,42 +0,0 @@ -package com.netgrif.application.engine.startup - -import com.netgrif.application.engine.importer.model.EventType -import com.netgrif.application.engine.petrinet.domain.I18nString -import com.netgrif.application.engine.petrinet.domain.events.Event -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Slf4j -@Component -@CompileStatic -class AnonymousRoleRunner extends AbstractOrderedCommandLineRunner { - - @Autowired - private ProcessRoleRepository repository - - @Override - void run(String... strings) throws Exception { - log.info("Creating anonymous process role") - - def role = repository.findAllByImportId(ProcessRole.ANONYMOUS_ROLE) - if (role && !role.isEmpty()) { - log.info("Anonymous role already exists") - return - } - - ProcessRole anonymousRole = new ProcessRole( - importId: ProcessRole.ANONYMOUS_ROLE, - name: new I18nString(ProcessRole.ANONYMOUS_ROLE), - description: "Anonymous system process role", - events: new LinkedHashMap() - ) - anonymousRole = repository.save(anonymousRole) - - if (anonymousRole == null) - log.error("Error saving anonymous process role") - } -} diff --git a/src/main/groovy/com/netgrif/application/engine/startup/ApplicationRoleRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/ApplicationRoleRunner.groovy new file mode 100644 index 00000000000..d3ea03d506f --- /dev/null +++ b/src/main/groovy/com/netgrif/application/engine/startup/ApplicationRoleRunner.groovy @@ -0,0 +1,61 @@ +package com.netgrif.application.engine.startup + +import com.netgrif.application.engine.authorization.domain.ApplicationRole +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService +import groovy.transform.CompileStatic +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Component + +@Component +@CompileStatic +class ApplicationRoleRunner extends AbstractOrderedCommandLineRunner { + + public static final String DEFAULT_APP_ROLE = "default" + public static final String ADMIN_APP_ROLE = "admin" + public static final String SYSTEM_ADMIN_APP_ROLE = "system_admin" + public static final String ANONYMOUS_APP_ROLE = "anonymous" + // TODO: release/8.0.0 application id should be from configuration + private static final String APPLICATION_ID = "application" + + + private Map applicationRoles + + @Autowired + private IRoleService service + + @Override + void run(String... strings) throws Exception { + Map appRoles = new HashMap<>() + + appRoles.put(DEFAULT_APP_ROLE, createAppRole(APPLICATION_ID, DEFAULT_APP_ROLE)) + appRoles.put(ADMIN_APP_ROLE, createAppRole(APPLICATION_ID, ADMIN_APP_ROLE)) + appRoles.put(SYSTEM_ADMIN_APP_ROLE, createAppRole(APPLICATION_ID, SYSTEM_ADMIN_APP_ROLE)) + appRoles.put(ANONYMOUS_APP_ROLE, createAppRole(APPLICATION_ID, ANONYMOUS_APP_ROLE)) + + this.applicationRoles = Collections.unmodifiableMap(appRoles) + } + + /** + * todo javadoc + * */ + ApplicationRole getAppRole(String roleName) { + if (roleName == null || applicationRoles == null) { + return null + } + return applicationRoles.get(roleName) + } + + /** + * todo javadoc + * */ + Collection getAllAppRoles() { + return applicationRoles.values() + } + + private ApplicationRole createAppRole(String applicationId, String importId) { + if (!service.existsApplicationRoleByImportId(importId)) { + return (ApplicationRole) service.save(new ApplicationRole(importId, applicationId)) + } + return service.findApplicationRoleByImportId(importId) + } +} \ No newline at end of file diff --git a/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy deleted file mode 100644 index 06d66206ab0..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package com.netgrif.application.engine.startup - -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService -import groovy.transform.CompileStatic -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Component -@CompileStatic -class AuthorityRunner extends AbstractOrderedCommandLineRunner { - - @Autowired - private IAuthorityService service - - @Override - void run(String... strings) throws Exception { - service.getOrCreate(Authority.user) - service.getOrCreate(Authority.admin) - service.getOrCreate(Authority.systemAdmin) - service.getOrCreate(Authority.anonymous) - } -} \ No newline at end of file diff --git a/src/main/groovy/com/netgrif/application/engine/startup/DashboardRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/DashboardRunner.groovy index 4c3690da982..d363539f696 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/DashboardRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/DashboardRunner.groovy @@ -1,6 +1,7 @@ package com.netgrif.application.engine.startup -import com.netgrif.application.engine.petrinet.domain.PetriNet + +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import groovy.util.logging.Slf4j @@ -34,23 +35,23 @@ class DashboardRunner extends AbstractOrderedCommandLineRunner { createDashboardTileNet() } - Optional createDashboardNet() { + Optional createDashboardNet() { importProcess("Petri net for filters", DASHBOARD_NET_IDENTIFIER, DASHBOARD_FILE_NAME) } - Optional createDashboardTileNet() { + Optional createDashboardTileNet() { importProcess("Petri net for filter preferences", DASHBOARD_TILE_NET_IDENTIFIER, DASHBOARD_TILE_FILE_NAME) } - Optional importProcess(String message, String netIdentifier, String netFileName) { - PetriNet filter = petriNetService.getNewestVersionByIdentifier(netIdentifier) + Optional importProcess(String message, String netIdentifier, String netFileName) { + Process filter = petriNetService.getNewestVersionByIdentifier(netIdentifier) if (filter != null) { log.info("${message} has already been imported.") return Optional.of(filter) } - Optional filterNet = helper.createNet(netFileName, VersionType.MAJOR, systemCreator.loggedSystem) + Optional filterNet = helper.createNet(netFileName, VersionType.MAJOR, systemCreator.loggedSystem) if (!filterNet.isPresent()) { log.error("Import of ${message} failed!") diff --git a/src/main/groovy/com/netgrif/application/engine/startup/DefaultFiltersRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/DefaultFiltersRunner.groovy index da3594dd345..75bbdacc561 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/DefaultFiltersRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/DefaultFiltersRunner.groovy @@ -1,8 +1,9 @@ package com.netgrif.application.engine.startup -import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authorization.service.interfaces.IUserService import com.netgrif.application.engine.petrinet.domain.I18nString -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField import com.netgrif.application.engine.petrinet.domain.dataset.Field import com.netgrif.application.engine.petrinet.domain.dataset.FilterField @@ -13,11 +14,13 @@ import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.QCase import com.netgrif.application.engine.workflow.domain.QTask import com.netgrif.application.engine.workflow.domain.Task +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams +import com.netgrif.application.engine.workflow.domain.params.SetDataParams +import com.netgrif.application.engine.workflow.domain.params.TaskParams import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import com.netgrif.application.engine.workflow.web.responsebodies.DataSet -import groovy.transform.CompileStatic import lombok.extern.slf4j.Slf4j import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component @@ -55,6 +58,9 @@ class DefaultFiltersRunner extends AbstractOrderedCommandLineRunner { @Autowired private IWorkflowService workflowService + @Autowired + private IIdentityService identityService + @Autowired private IUserService userService @@ -257,25 +263,32 @@ class DefaultFiltersRunner extends AbstractOrderedCommandLineRunner { boolean viewOrigin, boolean isImported ) { - PetriNet filterNet = this.petriNetService.getNewestVersionByIdentifier('filter') + Process filterNet = this.petriNetService.getNewestVersionByIdentifier('filter') if (filterNet == null) { return Optional.empty() } - def loggedUser = this.userService.getLoggedOrSystem() + def actorId = this.userService.systemUser.stringId - if (loggedUser.getStringId() == this.userService.getSystem().getStringId()) { - Case filterCase = this.workflowService.searchOne(QCase.case$.processIdentifier.eq("filter").and(QCase.case$.title.eq(title)).and(QCase.case$.author.id.eq(userService.getSystem().getStringId()))) - if (filterCase != null) { - return Optional.of(filterCase) - } + Case filterCase = this.workflowService.searchOne((QCase.case$.processIdentifier.eq("filter") + & QCase.case$.title.eq(title)) + & QCase.case$.authorId.eq(actorId)) + if (filterCase != null) { + return Optional.of(filterCase) } - Case filterCase = this.workflowService.createCase(filterNet.getStringId(), title, null, loggedUser.transformToLoggedUser()).getCase() + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(filterNet) + .title(title) + .authorId(actorId) + .build() + + filterCase = this.workflowService.createCase(createCaseParams).getCase() filterCase.setIcon(icon) filterCase = this.workflowService.save(filterCase) - Task newFilterTask = this.taskService.searchOne(QTask.task.transitionId.eq(AUTO_CREATE_TRANSITION).and(QTask.task.caseId.eq(filterCase.getStringId()))) - this.taskService.assignTask(newFilterTask, this.userService.getLoggedOrSystem()) + Task newFilterTask = this.taskService.searchOne(QTask.task.transitionId.eq(AUTO_CREATE_TRANSITION) + & QTask.task.caseId.eq(filterCase.getStringId())) + this.taskService.assignTask(new TaskParams(newFilterTask, actorId)) DataSet dataSet = new DataSet([ (FILTER_TYPE_FIELD_ID): new EnumerationMapField(rawValue: filterType), @@ -288,11 +301,11 @@ class DefaultFiltersRunner extends AbstractOrderedCommandLineRunner { } // TODO: release/8.0.0 join setData to one call - this.dataService.setData(newFilterTask, dataSet, superCreator.getSuperUser()) + this.dataService.setData(new SetDataParams(newFilterTask, dataSet, actorId)) if (isImported) { - this.dataService.setData(newFilterTask, new DataSet([ + this.dataService.setData(new SetDataParams(newFilterTask, new DataSet([ (IS_IMPORTED): new NumberField(rawValue: 1) - ] as Map>), superCreator.getSuperUser()) + ] as Map>), actorId)) } I18nString translatedTitle = new I18nString(title) @@ -302,7 +315,7 @@ class DefaultFiltersRunner extends AbstractOrderedCommandLineRunner { filterCase.dataSet.get(FILTER_I18N_TITLE_FIELD_ID).rawValue = translatedTitle workflowService.save(filterCase) - this.taskService.finishTask(newFilterTask, this.userService.getLoggedOrSystem()) + this.taskService.finishTask(new TaskParams(newFilterTask, actorId)) return Optional.of(this.workflowService.findOne(filterCase.getStringId())) } } diff --git a/src/main/groovy/com/netgrif/application/engine/startup/DefaultGroupRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/DefaultGroupRunner.groovy new file mode 100644 index 00000000000..dfca2f2014d --- /dev/null +++ b/src/main/groovy/com/netgrif/application/engine/startup/DefaultGroupRunner.groovy @@ -0,0 +1,41 @@ +package com.netgrif.application.engine.startup + +import com.netgrif.application.engine.authorization.domain.Group +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants +import com.netgrif.application.engine.authorization.service.interfaces.IGroupService +import groovy.transform.CompileStatic +import groovy.util.logging.Slf4j +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Component + +@Slf4j +@Component +@CompileStatic +class DefaultGroupRunner extends AbstractOrderedCommandLineRunner { + + @Autowired + private IGroupService service + + private Group defaultGroup + + @Override + void run(String... args) throws Exception { + Optional groupOpt = service.findByName(GroupConstants.DEFAULT_GROUP_NAME) + service.registerForbiddenKeywords(Set.of(GroupConstants.DEFAULT_GROUP_NAME)) + if (groupOpt.isPresent()) { + log.info("Found default group with id [{}]", groupOpt.get().stringId) + this.defaultGroup = groupOpt.get() + return + } + clearCache() + this.defaultGroup = service.getDefaultGroup() + } + + Group getDefaultGroup() { + return this.defaultGroup + } + + void clearCache() { + this.defaultGroup = null + } +} diff --git a/src/main/groovy/com/netgrif/application/engine/startup/DefaultRoleRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/DefaultRoleRunner.groovy deleted file mode 100644 index 9a6b8e7af37..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/startup/DefaultRoleRunner.groovy +++ /dev/null @@ -1,45 +0,0 @@ -package com.netgrif.application.engine.startup - -import com.netgrif.application.engine.importer.model.EventType -import com.netgrif.application.engine.petrinet.domain.I18nString -import com.netgrif.application.engine.petrinet.domain.events.Event -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.context.annotation.Profile -import org.springframework.stereotype.Component - -@Slf4j -@Component -@Profile("!update") -@CompileStatic -class DefaultRoleRunner extends AbstractOrderedCommandLineRunner { - - @Autowired - private ProcessRoleRepository repository - - @Override - void run(String... strings) throws Exception { - log.info("Creating default process role") - - def role = repository.findAllByName_DefaultValue(ProcessRole.DEFAULT_ROLE) - if (role) { - log.info("Default role already exists") - return - } - - ProcessRole defaultRole = new ProcessRole( - importId: ProcessRole.DEFAULT_ROLE, - name: new I18nString(ProcessRole.DEFAULT_ROLE), - description: "Default system process role", - events: new LinkedHashMap() - ) - defaultRole = repository.save(defaultRole) - - if (defaultRole == null) { - log.error("Error saving default process role") - } - } -} diff --git a/src/main/groovy/com/netgrif/application/engine/startup/DemoRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/DemoRunner.groovy index 0a967314dd3..2df3d74db3a 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/DemoRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/DemoRunner.groovy @@ -1,7 +1,7 @@ package com.netgrif.application.engine.startup -import com.netgrif.application.engine.elastic.domain.ElasticCaseRepository -import com.netgrif.application.engine.elastic.domain.ElasticTaskRepository +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticCaseRepository +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticTaskRepository import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import com.netgrif.application.engine.workflow.domain.repositories.TaskRepository diff --git a/src/main/groovy/com/netgrif/application/engine/startup/FilterRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/FilterRunner.groovy index bf68e37691e..05ef4239bcc 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/FilterRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/FilterRunner.groovy @@ -1,9 +1,9 @@ package com.netgrif.application.engine.startup -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.authorization.service.interfaces.IUserService +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome import groovy.transform.CompileStatic import groovy.util.logging.Slf4j import org.springframework.beans.factory.annotation.Autowired @@ -21,7 +21,7 @@ class FilterRunner extends AbstractOrderedCommandLineRunner { private ImportHelper helper @Autowired - private SystemUserRunner systemCreator + private IUserService userService private static final String FILTER_FILE_NAME = "engine-processes/filter.xml" public static final String FILTER_PETRI_NET_IDENTIFIER = "filter" @@ -43,30 +43,30 @@ class FilterRunner extends AbstractOrderedCommandLineRunner { createExportFiltersNet() } - Optional createFilterNet() { + Optional createFilterNet() { importProcess("Petri net for filters", FILTER_PETRI_NET_IDENTIFIER, FILTER_FILE_NAME) } - Optional createPreferenceItemNet() { + Optional createPreferenceItemNet() { importProcess("Petri net for filter preferences", PREFERRED_ITEM_NET_IDENTIFIER, PREFERRED_ITEM_FILE_NAME) } - Optional createImportFiltersNet() { + Optional createImportFiltersNet() { importProcess("Petri net for importing filters", IMPORT_NET_IDENTIFIER, IMPORT_FILTER_FILE_NAME) } - Optional createExportFiltersNet() { + Optional createExportFiltersNet() { importProcess("Petri net for exporting filters", EXPORT_NET_IDENTIFIER, EXPORT_FILTER_FILE_NAME) } - Optional importProcess(String message, String netIdentifier, String netFileName) { - PetriNet filter = petriNetService.getNewestVersionByIdentifier(netIdentifier) + Optional importProcess(String message, String netIdentifier, String netFileName) { + Process filter = petriNetService.getNewestVersionByIdentifier(netIdentifier) if (filter != null) { log.info("${message} has already been imported.") return Optional.of(filter) } - Optional filterNet = helper.createNet(netFileName, VersionType.MAJOR, systemCreator.loggedSystem) + Optional filterNet = helper.createNet(netFileName, VersionType.MAJOR, userService.getSystemUser().stringId) if (!filterNet.isPresent()) { log.error("Import of ${message} failed!") diff --git a/src/main/groovy/com/netgrif/application/engine/startup/FinisherRunnerSuperCreator.groovy b/src/main/groovy/com/netgrif/application/engine/startup/FinisherRunnerSuperCreator.groovy deleted file mode 100644 index 1651e2adeb9..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/startup/FinisherRunnerSuperCreator.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package com.netgrif.application.engine.startup - -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty -import org.springframework.stereotype.Component - -@Slf4j -@Component -@ConditionalOnProperty(value = "admin.create-super", matchIfMissing = true) -@CompileStatic -class FinisherRunnerSuperCreator extends AbstractOrderedCommandLineRunner { - - @Autowired - private SuperCreator superCreator - - @Override - void run(String... strings) throws Exception { - superCreator.setAllToSuperUser() - log.info("Super Creator update") - } -} \ No newline at end of file diff --git a/src/main/groovy/com/netgrif/application/engine/startup/GroupRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/GroupRunner.groovy deleted file mode 100644 index 01406166eab..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/startup/GroupRunner.groovy +++ /dev/null @@ -1,68 +0,0 @@ -package com.netgrif.application.engine.startup - -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.orgstructure.groups.config.GroupConfigurationProperties -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService -import com.netgrif.application.engine.petrinet.domain.PetriNet -import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty -import org.springframework.stereotype.Component - -@ConditionalOnProperty(value = "nae.group.default.enabled", - havingValue = "true", - matchIfMissing = true) -@Component -@Slf4j -@CompileStatic -class GroupRunner extends AbstractOrderedCommandLineRunner { - - @Autowired - private ImportHelper helper - - @Autowired - private INextGroupService nextGroupService - - @Autowired - private IUserService userService - - @Autowired - private SystemUserRunner systemCreator - - @Autowired - private IPetriNetService petriNetService - - @Autowired - private GroupConfigurationProperties groupProperties - - private static final String GROUP_FILE_NAME = "engine-processes/org_group.xml"; - private static final String GROUP_PETRINET_IDENTIFIER = "org_group" - public static final String DEFAULT_GROUP_TITLE = "Default system group" - - @Override - void run(String... args) throws Exception { - createDefaultGroup() - } - - Optional createDefaultGroup() { - PetriNet group - if ((group = petriNetService.getNewestVersionByIdentifier(GROUP_PETRINET_IDENTIFIER)) != null) { - log.info("Petri net for groups has already been imported.") - return Optional.of(group) - } - - Optional groupNet = helper.createNet(GROUP_FILE_NAME, VersionType.MAJOR, systemCreator.loggedSystem) - - if (!groupNet.present) { - log.error("Import of petri net for groups failed!") - return groupNet - } - if (groupProperties.isSystemEnabled()) { - nextGroupService.createDefaultSystemGroup(userService.getLoggedOrSystem()) - } - return groupNet; - } -} diff --git a/src/main/groovy/com/netgrif/application/engine/startup/ImpersonationRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/ImpersonationRunner.groovy deleted file mode 100644 index d2766a4e413..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/startup/ImpersonationRunner.groovy +++ /dev/null @@ -1,53 +0,0 @@ -package com.netgrif.application.engine.startup - -import com.netgrif.application.engine.petrinet.domain.PetriNet -import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import groovy.util.logging.Slf4j -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Slf4j -@Component -class ImpersonationRunner extends AbstractOrderedCommandLineRunner { - - @Autowired - protected IPetriNetService petriNetService - - @Autowired - protected ImportHelper helper - - @Autowired - protected SystemUserRunner systemCreator - - protected static final String IMPERSONATION_CONFIG_FILE_NAME = "engine-processes/impersonation_config.xml" - public static final String IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER = "impersonation_config" - - protected static final String IMPERSONATION_CONFIG_USER_SELECT_FILE_NAME = "engine-processes/impersonation_users_select.xml" - public static final String IMPERSONATION_CONFIG_USER_SELECT_PETRI_NET_IDENTIFIER = "impersonation_users_select" - - @Override - void run(String... args) throws Exception { - createConfigNets() - } - - void createConfigNets() { - importProcess("Petri net for impersonation config", IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER, IMPERSONATION_CONFIG_FILE_NAME) - importProcess("Petri net for impersonation user select", IMPERSONATION_CONFIG_USER_SELECT_PETRI_NET_IDENTIFIER, IMPERSONATION_CONFIG_USER_SELECT_FILE_NAME) - } - - Optional importProcess(String message, String netIdentifier, String netFileName) { - PetriNet foundNet = petriNetService.getNewestVersionByIdentifier(netIdentifier) - if (foundNet != null) { - log.info("${message} has already been imported.") - return Optional.of(foundNet) - } - - Optional net = helper.createNet(netFileName, VersionType.MAJOR, systemCreator.loggedSystem) - if (!net.isPresent()) { - log.error("Import of ${message} failed!") - } - - return net - } -} diff --git a/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy b/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy index b03c6f26aa9..030f8996881 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy @@ -1,22 +1,31 @@ package com.netgrif.application.engine.startup -import com.netgrif.application.engine.auth.domain.* -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService + +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.LoggedIdentity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService + +import com.netgrif.application.engine.authorization.domain.Role +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService +import com.netgrif.application.engine.authorization.service.interfaces.IUserService +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService import com.netgrif.application.engine.petrinet.domain.DataRef -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.service.ProcessRoleService import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.petrinet.service.interfaces.IUriService import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.AssignTaskEventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.CancelTaskEventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.FinishTaskEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.AssignTaskEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.CancelTaskEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.FinishTaskEventOutcome +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams +import com.netgrif.application.engine.workflow.domain.params.GetDataParams +import com.netgrif.application.engine.workflow.domain.params.SetDataParams +import com.netgrif.application.engine.workflow.domain.params.TaskParams import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.ITaskService @@ -24,13 +33,13 @@ import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowServi import com.netgrif.application.engine.workflow.web.responsebodies.DataSet import com.netgrif.application.engine.workflow.web.responsebodies.TaskReference import groovy.util.logging.Slf4j -import org.slf4j.Logger -import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired import org.springframework.core.io.ClassPathResource import org.springframework.core.io.ResourceLoader import org.springframework.stereotype.Component +import java.util.stream.Collectors + @Slf4j @Component class ImportHelper { @@ -38,14 +47,17 @@ class ImportHelper { @Autowired private PetriNetRepository petriNetRepository + @Autowired + private IIdentityService identityService + @Autowired private IUserService userService @Autowired - private CaseRepository caseRepository + private ISessionManagerService sessionManagerService @Autowired - private IAuthorityService authorityService + private CaseRepository caseRepository @Autowired private ITaskService taskService @@ -66,114 +78,88 @@ class ImportHelper { private IWorkflowService workflowService @Autowired - private INextGroupService groupService - - @Autowired - private ProcessRoleService processRoleService + private IRoleService roleService @Autowired private IUriService uriService - @SuppressWarnings("GroovyAssignabilityCheck") - Map createAuthorities(Map authorities) { - HashMap authoritities = new HashMap<>() - authorities.each { authority -> - authoritities.put(authority.key, authorityService.getOrCreate(authority.value)) - } - - log.info("Creating ${authoritities.size()} authorities") - return authoritities + Optional createNet(String fileName, String release, String actorId = userService.getSystemUser()?.stringId, + String uriNodeId = uriService.getRoot().stringId) { + return createNet(fileName, VersionType.valueOf(release.trim().toUpperCase()), actorId, uriNodeId) } - Authority createAuthority(String name) { - log.info("Creating authority $name") - return authorityService.getOrCreate(name) - } - - Optional createNet(String fileName, String release, LoggedUser author = userService.getSystem().transformToLoggedUser(), String uriNodeId = uriService.getRoot().stringId) { - return createNet(fileName, VersionType.valueOf(release.trim().toUpperCase()), author, uriNodeId) - } - - Optional createNet(String fileName, VersionType release = VersionType.MAJOR, LoggedUser author = userService.getSystem().transformToLoggedUser(), String uriNodeId = uriService.getRoot().stringId) { + Optional createNet(String fileName, VersionType release = VersionType.MAJOR, String actorId = userService.getSystemUser()?.stringId, + String uriNodeId = uriService.getRoot().stringId) { InputStream netStream = new ClassPathResource("petriNets/$fileName" as String).inputStream - PetriNet petriNet = petriNetService.importPetriNet(netStream, release, author, uriNodeId).getNet() + Process petriNet = petriNetService.importProcess(new ImportProcessParams(netStream, release, actorId, uriNodeId)).getProcess() log.info("Imported '${petriNet?.title?.defaultValue}' ['${petriNet?.identifier}', ${petriNet?.stringId}]") return Optional.of(petriNet) } - Optional upsertNet(String filename, String identifier, VersionType release = VersionType.MAJOR, LoggedUser author = userService.getSystem().transformToLoggedUser()) { - PetriNet petriNet = petriNetService.getNewestVersionByIdentifier(identifier) + Optional upsertNet(String filename, String identifier, VersionType release = VersionType.MAJOR, + String actorId = userService.getSystemUser()?.stringId) { + Process petriNet = petriNetService.getNewestVersionByIdentifier(identifier) if (!petriNet) { - return createNet(filename, release, author) + return createNet(filename, release, actorId) } + log.info("Process with identifier [{}] already exists", identifier) return Optional.of(petriNet) } - ProcessRole getProcessRoleByImportId(PetriNet net, String roleId) { - ProcessRole role = net.roles.values().find { it -> it.importId == roleId } - return role - } + /** + * todo javadoc + * */ + Identity createIdentity(IdentityParams params, List roles) { + Identity identity = identityService.createWithDefaultUser(params) - Map getProcessRolesByImportId(PetriNet net, Map importId) { - HashMap roles = new HashMap<>() - importId.each { it -> - roles.put(it.getKey(), getProcessRoleByImportId(net, it.getValue())) - } - return roles - } + Set roleIds = roles.stream().map { role -> role.stringId }.collect(Collectors.toSet()) + roleService.assignRolesToActor(identity.getMainActorId(), roleIds) - Map getProcessRoles(PetriNet net) { - List roles = processRoleService.findAll(net.stringId) - Map map = [:] - net.roles.values().each { netRole -> - map[netRole.name.getDefaultValue()] = roles.find { it.roleId == netRole.stringId } - } - return map - } + log.info("Identity [{}][{}] created with default user [{}].", identity.getStringId(), identity.getUsername(), + identity.getMainActorId()) - IUser createUser(User user, Authority[] authorities, ProcessRole[] roles) { - authorities.each { user.addAuthority(it) } - roles.each { user.addProcessRole(it) } - user.state = UserState.ACTIVE - user = userService.saveNew(user) - log.info("User $user.name $user.surname created") - return user + return identity } - Case createCase(String title, PetriNet net, LoggedUser user) { - return workflowService.createCase(net.getStringId(), title, "", user).getCase() + Case createCase(String title, Process net, LoggedIdentity author) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title(title) + .authorId(author.activeActorId) + .build() + return workflowService.createCase(createCaseParams).getCase() } - Case createCase(String title, PetriNet net) { - return createCase(title, net, userService.getSystem().transformToLoggedUser()) + Case createCase(String title, Process net) { + return createCase(title, net, sessionManagerService.loggedIdentity) } - Case createCaseAsSuper(String title, PetriNet net) { - return createCase(title, net, superCreator.loggedSuper ?: userService.getSystem().transformToLoggedUser()) + Case createCaseAsSuper(String title, Process net) { + return createCase(title, net, superCreator.loggedSuper) } - AssignTaskEventOutcome assignTask(String taskTitle, String caseId, LoggedUser author) { - return taskService.assignTask(author, getTaskId(taskTitle, caseId)) + AssignTaskEventOutcome assignTask(String taskTitle, String caseId, LoggedIdentity assignee) { + return taskService.assignTask(new TaskParams(getTaskId(taskTitle, caseId), assignee.activeActorId)) } AssignTaskEventOutcome assignTaskToSuper(String taskTitle, String caseId) { - return assignTask(taskTitle, caseId, superCreator.loggedSuper ?: userService.getSystem().transformToLoggedUser()) + return assignTask(taskTitle, caseId, superCreator.loggedSuper) } - FinishTaskEventOutcome finishTask(String taskTitle, String caseId, LoggedUser author) { - return taskService.finishTask(author, getTaskId(taskTitle, caseId)) + FinishTaskEventOutcome finishTask(String taskTitle, String caseId, LoggedIdentity assignee) { + return taskService.finishTask(new TaskParams(getTaskId(taskTitle, caseId), assignee.activeActorId)) } FinishTaskEventOutcome finishTaskAsSuper(String taskTitle, String caseId) { - return finishTask(taskTitle, caseId, superCreator.loggedSuper ?: userService.getSystem().transformToLoggedUser()) + return finishTask(taskTitle, caseId, superCreator.loggedSuper) } - CancelTaskEventOutcome cancelTask(String taskTitle, String caseId, LoggedUser user) { - return taskService.cancelTask(user, getTaskId(taskTitle, caseId)) + CancelTaskEventOutcome cancelTask(String taskTitle, String caseId, LoggedIdentity assignee) { + return taskService.cancelTask(new TaskParams(getTaskId(taskTitle, caseId), assignee.activeActorId)) } CancelTaskEventOutcome cancelTaskAsSuper(String taskTitle, String caseId) { - return cancelTask(taskTitle, caseId, superCreator.loggedSuper ?: userService.getSystem().transformToLoggedUser()) + return cancelTask(taskTitle, caseId, superCreator.loggedSuper) } String getTaskId(String taskTitle, String caseId) { @@ -182,7 +168,7 @@ class ImportHelper { } SetDataEventOutcome setTaskData(String taskId, DataSet dataSet) { - dataService.setData(taskId, dataSet, superCreator.getSuperUser()) + dataService.setData(new SetDataParams(taskId, dataSet, userService.getSystemUser().stringId)) } SetDataEventOutcome setTaskData(String taskTitle, String caseId, DataSet data) { @@ -190,10 +176,6 @@ class ImportHelper { } List getTaskData(String taskTitle, String caseId) { - return dataService.getData(getTaskId(taskTitle, caseId), superCreator.getSuperUser()).getData() - } - - void updateSuperUser() { - superCreator.setAllToSuperUser(); + return dataService.getData(new GetDataParams(getTaskId(taskTitle, caseId), userService.getSystemUser().stringId)).getData() } } diff --git a/src/main/groovy/com/netgrif/application/engine/startup/MongoDbRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/MongoDbRunner.groovy index 09e6a7121a3..52856660a95 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/MongoDbRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/MongoDbRunner.groovy @@ -7,10 +7,8 @@ import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Profile import org.springframework.data.mapping.context.MappingContext import org.springframework.data.mongodb.core.MongoTemplate -import org.springframework.data.mongodb.core.index.IndexOperations import org.springframework.data.mongodb.core.index.IndexResolver import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver -import org.springframework.data.mongodb.core.mapping.Document import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty import org.springframework.stereotype.Component diff --git a/src/main/groovy/com/netgrif/application/engine/startup/RunnerController.groovy b/src/main/groovy/com/netgrif/application/engine/startup/RunnerController.groovy index d4ee2174a85..339d9a245db 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/RunnerController.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/RunnerController.groovy @@ -1,5 +1,6 @@ package com.netgrif.application.engine.startup + import org.springframework.stereotype.Component @Component @@ -10,24 +11,23 @@ class RunnerController { MongoDbRunner, StorageRunner, RuleEngineRunner, - DefaultRoleRunner, - AnonymousRoleRunner, - AuthorityRunner, - SystemUserRunner, + ApplicationRoleRunner, AllDataTransitionRunner, UriRunner, + SystemProcessRunner, + DefaultGroupRunner, + SystemUserRunner, + AnonymousIdentityRunner, FunctionsCacheRunner, FilterRunner, - GroupRunner, DefaultFiltersRunner, - ImpersonationRunner, DashboardRunner, SuperCreator, FlushSessionsRunner, MailRunner, DemoRunner, QuartzSchedulerRunner, - FinisherRunnerSuperCreator, + ValidationRunner, FinisherRunner, ] diff --git a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy index aad31ba629e..390b86fdd91 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy @@ -1,96 +1,81 @@ package com.netgrif.application.engine.startup -import com.netgrif.application.engine.auth.domain.* -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService -import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.LoggedIdentity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authorization.domain.Role +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService +import com.netgrif.application.engine.authorization.service.interfaces.IUserService import com.netgrif.application.engine.configuration.properties.SuperAdminConfiguration -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService +import com.netgrif.application.engine.petrinet.domain.dataset.TextField import groovy.transform.CompileStatic import groovy.util.logging.Slf4j import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.context.annotation.Lazy import org.springframework.stereotype.Component @Slf4j -@ConditionalOnProperty(value = "admin.create-super", matchIfMissing = true) @Component @CompileStatic +@ConditionalOnProperty(value = "admin.create-super", matchIfMissing = true) class SuperCreator extends AbstractOrderedCommandLineRunner { @Autowired - private IAuthorityService authorityService + private ApplicationRoleRunner applicationRoleRunner @Autowired - private IUserService userService + private IIdentityService identityService + @Lazy @Autowired - private INextGroupService groupService + private IUserService userService @Autowired - private IProcessRoleService processRoleService + private IRoleService roleService @Autowired private SuperAdminConfiguration configuration - private IUser superUser + private Identity superIdentity @Override void run(String... strings) { - log.info("Creating Super user") + log.info("Creating Super identity") createSuperUser() } private void createSuperUser() { - Authority adminAuthority = authorityService.getOrCreate(Authority.admin) - Authority systemAuthority = authorityService.getOrCreate(Authority.systemAdmin) - - IUser superUser = userService.findByEmail(configuration.email) - if (superUser != null) { - log.info("Super user detected") - this.superUser = superUser + Optional superIdentityOpt = identityService.findByUsername(configuration.email) + if (superIdentityOpt.isPresent()) { + log.info("Super identity detected") + this.superIdentity = superIdentityOpt.get() return } - this.superUser = userService.saveNew(new User( - name: configuration.name, - surname: configuration.surname, - email: configuration.email, - password: configuration.password, - state: UserState.ACTIVE, - authorities: [adminAuthority, systemAuthority] as Set, - processRoles: processRoleService.findAll() as Set)) - log.info("Super user created") - } - - void setAllToSuperUser() { - setAllGroups() - setAllProcessRoles() - setAllAuthorities() - log.info("Super user updated") - } - - void setAllGroups() { - groupService.findAllGroups().each { - groupService.addUser(superUser, it) - } - } - - void setAllProcessRoles() { - superUser.setProcessRoles(processRoleService.findAll() as Set) - superUser = userService.save(superUser) as IUser - } - - void setAllAuthorities() { - superUser.setAuthorities(authorityService.findAll() as Set) - superUser = userService.save(superUser) as IUser + this.superIdentity = identityService.createWithDefaultUser(IdentityParams.with() + .username(new TextField(configuration.email)) + .firstname(new TextField(configuration.name)) + .lastname(new TextField(configuration.surname)) + .password(new TextField(configuration.password)) + .build()) + + identityService.registerForbiddenKeywords(Set.of(configuration.email)) + userService.registerForbiddenKeywords(Set.of(configuration.email)) + + Role adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE) + Role systemAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.SYSTEM_ADMIN_APP_ROLE) + roleService.assignRolesToActor(this.superIdentity.toSession().activeActorId, + [adminAppRole.stringId, systemAppRole.stringId] as Set) + + log.info("Super identity created with actor") } - IUser getSuperUser() { - return superUser + Identity getSuperIdentity() { + return this.superIdentity } - LoggedUser getLoggedSuper() { - return superUser.transformToLoggedUser() + LoggedIdentity getLoggedSuper() { + return superIdentity.toSession() } } diff --git a/src/main/groovy/com/netgrif/application/engine/startup/SystemProcessRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/SystemProcessRunner.groovy new file mode 100644 index 00000000000..c9f27239e93 --- /dev/null +++ b/src/main/groovy/com/netgrif/application/engine/startup/SystemProcessRunner.groovy @@ -0,0 +1,48 @@ +package com.netgrif.application.engine.startup + +import com.netgrif.application.engine.authentication.domain.constants.IdentityConstants +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants +import com.netgrif.application.engine.authorization.domain.constants.UserConstants; +import groovy.util.logging.Slf4j +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +class SystemProcessRunner extends AbstractOrderedCommandLineRunner { + + @Autowired + private ImportHelper helper + + @Override + void run(String... args) throws Exception { + Set importData = getSystemProcesses() + importData.each { processData -> importProcess(processData) } + } + + private Set getSystemProcesses() { + // todo: release/8.0.0 make it automatische + return [ + new ImportData(IdentityConstants.PROCESS_IDENTIFIER, IdentityConstants.FILE_PATH), + new ImportData(UserConstants.PROCESS_IDENTIFIER, UserConstants.FILE_PATH), + new ImportData(GroupConstants.PROCESS_IDENTIFIER, GroupConstants.FILE_PATH) + ] as Set + } + + /** + * todo javadoc + * */ + private void importProcess(ImportData importData) { + helper.upsertNet(importData.filePath, importData.processIdentifier) + } + + class ImportData { + protected String processIdentifier + protected String filePath + + ImportData(String processIdentifier, String filePath) { + this.processIdentifier = processIdentifier + this.filePath = filePath + } + } +} diff --git a/src/main/groovy/com/netgrif/application/engine/startup/SystemUserRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/SystemUserRunner.groovy index 2c9bc88730a..72f3192937b 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/SystemUserRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/SystemUserRunner.groovy @@ -1,38 +1,62 @@ package com.netgrif.application.engine.startup -import com.netgrif.application.engine.auth.domain.IUser -import com.netgrif.application.engine.auth.domain.LoggedUser -import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.authentication.domain.constants.SystemUserConstants +import com.netgrif.application.engine.authorization.domain.Role +import com.netgrif.application.engine.authorization.domain.User +import com.netgrif.application.engine.authorization.domain.params.UserParams +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService +import com.netgrif.application.engine.authorization.service.interfaces.IUserService +import com.netgrif.application.engine.petrinet.domain.dataset.TextField import groovy.transform.CompileStatic +import groovy.util.logging.Slf4j import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.context.annotation.Lazy import org.springframework.stereotype.Component +@Slf4j @Component -@ConditionalOnProperty(value = "admin.create-system-user", matchIfMissing = true) @CompileStatic class SystemUserRunner extends AbstractOrderedCommandLineRunner { - public static final String SYSTEM_USER_EMAIL = "engine@netgrif.com" - public static final String SYSTEM_USER_NAME = "application" - public static final String SYSTEM_USER_SURNAME = "engine" - + @Lazy @Autowired - private IUserService service + private IUserService userService - private IUser systemUser + @Autowired + private IRoleService roleService - IUser createSystemUser() { - return service.createSystemUser() - } + @Autowired + private ApplicationRoleRunner applicationRoleRunner - LoggedUser getLoggedSystem() { - return this.systemUser.transformToLoggedUser() - } + private User systemUser @Override void run(String... strings) throws Exception { - this.systemUser = createSystemUser() + Optional systemOpt = userService.findByEmail(SystemUserConstants.EMAIL) + if (systemOpt.isPresent()) { + this.systemUser = systemOpt.get() + return + } + this.systemUser = createSystemIdentityWithUser() } + private User createSystemIdentityWithUser() { + User systemUser = userService.create(UserParams.with() + .email(new TextField(SystemUserConstants.EMAIL)) + .firstname(new TextField(SystemUserConstants.FIRSTNAME)) + .lastname(new TextField(SystemUserConstants.LASTNAME)) + .build()) + + Role adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE) + Role systemAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.SYSTEM_ADMIN_APP_ROLE) + roleService.assignRolesToActor(systemUser.stringId, [adminAppRole.stringId, systemAppRole.stringId] as Set) + + userService.registerForbiddenKeywords(Set.of(systemUser.getEmail())) + log.info("Created system user [{}] with id [{}].", systemUser.getEmail(), systemUser.stringId) + return systemUser + } + + User getSystemUser() { + return systemUser; + } } diff --git a/src/main/groovy/com/netgrif/application/engine/startup/ValidationRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/ValidationRunner.groovy new file mode 100644 index 00000000000..0e6e36cd3c9 --- /dev/null +++ b/src/main/groovy/com/netgrif/application/engine/startup/ValidationRunner.groovy @@ -0,0 +1,60 @@ +package com.netgrif.application.engine.startup + + +import com.netgrif.application.engine.validations.interfaces.IValidationService +import com.netgrif.application.engine.workflow.domain.Case +import com.netgrif.application.engine.workflow.domain.QCase +import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository +import com.querydsl.core.types.Predicate +import groovy.util.logging.Slf4j +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.data.domain.PageRequest +import org.springframework.stereotype.Component + +@Slf4j +@Component +class ValidationRunner extends AbstractOrderedCommandLineRunner { + + private static final int PAGE_SIZE = 100 + public static final String VALIDATION_FILE_NAME = "engine-processes/validations/validation.xml" + public static final String VALIDATION_PETRI_NET_IDENTIFIER = "validation" + public static final String VALIDATION_ACTIVE_PLACE_ID = "active" + public static final String VALIDATION_NAME_FIELD_ID = "name" + public static final String VALIDATION_GROOVY_DEFINITION_FIELD_ID = "validation_definition_groovy" + + @Autowired + private ImportHelper helper + + @Autowired + private IValidationService validationService + + @Autowired + private CaseRepository caseRepository + + @Override + void run(String... strings) throws Exception { + log.info("Starting validation runner") + + helper.upsertNet(VALIDATION_FILE_NAME, VALIDATION_PETRI_NET_IDENTIFIER) + // TODO: release/8.0.0 only active, .get() does not exist on QMap + Predicate predicate = QCase.case$.processIdentifier.eq(VALIDATION_PETRI_NET_IDENTIFIER) + long numberActiveValidations = caseRepository.count(predicate) + int pageCount = (int) (numberActiveValidations / PAGE_SIZE) + 1 + pageCount.times { pageNum -> + caseRepository.findAll(predicate, PageRequest.of(pageNum, PAGE_SIZE)) + .getContent() + .each { Case validationCase -> + Integer marking = validationCase.activePlaces[VALIDATION_ACTIVE_PLACE_ID] + if (marking == null || marking == 0) { + return + } + validationService.registerValidation( + validationCase.getDataSet().get(VALIDATION_NAME_FIELD_ID).rawValue as String, + validationCase.getDataSet().get(VALIDATION_GROOVY_DEFINITION_FIELD_ID).rawValue as String + ) + } + } + + log.info("Validation runner finished, [{}] validations successfully imported", numberActiveValidations) + } +} \ No newline at end of file diff --git a/src/main/groovy/com/netgrif/application/engine/validation/domain/ValidationDataInput.groovy b/src/main/groovy/com/netgrif/application/engine/validation/domain/ValidationDataInput.groovy deleted file mode 100644 index 97e6f6865a1..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/validation/domain/ValidationDataInput.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package com.netgrif.application.engine.validation.domain - -import com.netgrif.application.engine.petrinet.domain.I18nString -import com.netgrif.application.engine.petrinet.domain.dataset.Field -import lombok.AllArgsConstructor -import lombok.Data - -class ValidationDataInput { - - Field data - - I18nString validationMessage - - Locale locale - - String validationRegex - - ValidationDataInput(Field data, I18nString validationMessage, Locale locale, String validationRegex) { - this.data = data - this.validationMessage = validationMessage - this.locale = locale - this.validationRegex = validationRegex - } -} diff --git a/src/main/groovy/com/netgrif/application/engine/validation/models/AbstractFieldValidation.groovy b/src/main/groovy/com/netgrif/application/engine/validation/models/AbstractFieldValidation.groovy deleted file mode 100644 index 16b2c490718..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/validation/models/AbstractFieldValidation.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package com.netgrif.application.engine.validation.models - -import com.netgrif.application.engine.validation.domain.ValidationDataInput - -class AbstractFieldValidation implements Serializable { - - private static final long serialVersionUID = 3287601522204188694L - - void notempty(ValidationDataInput validationData) { - if (validationData.getData().getValue() == null || validationData.getData().getRawValue() == null) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } -} diff --git a/src/main/groovy/com/netgrif/application/engine/validation/models/BooleanFieldValidation.groovy b/src/main/groovy/com/netgrif/application/engine/validation/models/BooleanFieldValidation.groovy deleted file mode 100644 index 201e8460ce0..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/validation/models/BooleanFieldValidation.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package com.netgrif.application.engine.validation.models - -import com.netgrif.application.engine.petrinet.domain.dataset.BooleanField -import com.netgrif.application.engine.validation.domain.ValidationDataInput - -class BooleanFieldValidation extends AbstractFieldValidation { - -// REQUIRED_TRUE = 'requiredTrue' -// REQUIRED = 'required' - - void requiredtrue(ValidationDataInput validationData) { - Boolean value = ((BooleanField) validationData.getData()).getRawValue() - if (!(value == true) || value == null) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } -} diff --git a/src/main/groovy/com/netgrif/application/engine/validation/models/DateFieldValidation.groovy b/src/main/groovy/com/netgrif/application/engine/validation/models/DateFieldValidation.groovy deleted file mode 100644 index 3beaecd6294..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/validation/models/DateFieldValidation.groovy +++ /dev/null @@ -1,122 +0,0 @@ -package com.netgrif.application.engine.validation.models - -import com.netgrif.application.engine.petrinet.domain.dataset.DateField -import com.netgrif.application.engine.petrinet.domain.dataset.DateTimeField -import com.netgrif.application.engine.petrinet.domain.dataset.Field -import com.netgrif.application.engine.validation.domain.ValidationDataInput -import groovy.util.logging.Slf4j - -import java.time.DayOfWeek -import java.time.LocalDate -import java.time.format.DateTimeFormatter -import java.time.format.DateTimeParseException -import java.time.temporal.ChronoField - -@Slf4j -class DateFieldValidation extends AbstractFieldValidation { - -// BETWEEN = 'between' -// WORKDAY = 'workday' -// WEEKEND = 'weekend' -// REQUIRED = 'required', -// VALID_BETWEEN = 'validBetween', -// VALID_WORKDAY = 'validWorkday', -// VALID_WEEKEND = 'validWeekend' - -// between today,future -// between past,today -// between 2020-03-03,today - - public static final String FUTURE = "future" - public static final String TODAY = "today" - public static final String PAST = "past" - public static final String NOW = "now" - - void between(ValidationDataInput validationData) { - LocalDate updateDate_TODAY = LocalDate.now() - List regex = validationData.getValidationRegex().trim().split(",") - LocalDate setDate = getDateValue(validationData.getData()) - - if (regex.size() == 2) { - def fromDate = parseStringToLocalDate(regex.get(0)) != null ? parseStringToLocalDate(regex.get(0)) : regex.get(0) - def toDate = parseStringToLocalDate(regex.get(1)) != null ? parseStringToLocalDate(regex.get(1)) : regex.get(1) - if ((fromDate == TODAY || fromDate == NOW) && toDate == FUTURE) { - if (setDate < updateDate_TODAY) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else if (fromDate == PAST && (toDate == TODAY || toDate == NOW)) { - if (setDate > updateDate_TODAY) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else if (fromDate == PAST && (toDate instanceof LocalDate)) { - if (setDate > toDate) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else if (fromDate == TODAY && (toDate instanceof LocalDate)) { - if (setDate < toDate || setDate > updateDate_TODAY) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else if ((fromDate instanceof LocalDate) && toDate == TODAY) { - if (setDate < fromDate || setDate > updateDate_TODAY) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else if (toDate == FUTURE && (fromDate instanceof LocalDate)) { - if (setDate < fromDate) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else if ((fromDate instanceof LocalDate) && (toDate instanceof LocalDate)) { - if (setDate > toDate || setDate < fromDate) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - } - - void workday(ValidationDataInput validationData) { - LocalDate setDate = getDateValue(validationData.getData()) - if (isWeekend(setDate)) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - - void weekend(ValidationDataInput validationData) { - LocalDate setDate = getDateValue(validationData.getData()) - if (!isWeekend(setDate)) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - - // TODO: release/8.0.0 Refactor, each type own validator with common functions - LocalDate getDateValue(Field field) { - if (field instanceof DateField) { - return ((DateField) field).getRawValue() - } - throw new IllegalArgumentException("Cannot validate field " + field.stringId + " of type " + field.type + " with date validation") - } - - protected static boolean isWeekend(LocalDate day) { - DayOfWeek dayOfWeek = DayOfWeek.of(day.get(ChronoField.DAY_OF_WEEK)); - return dayOfWeek == DayOfWeek.SUNDAY || dayOfWeek == DayOfWeek.SATURDAY; - } - - protected LocalDate parseStringToLocalDate(String stringDate) { - if (stringDate == null) { - return null - } - List patterns = Arrays.asList("dd.MM.yyyy") - try { - return LocalDate.parse(stringDate, DateTimeFormatter.BASIC_ISO_DATE) - } catch (DateTimeParseException ignored) { - try { - return LocalDate.parse(stringDate, DateTimeFormatter.ISO_DATE) - } catch (DateTimeParseException ignored2) { - for (String pattern : patterns) { - try { - return LocalDate.parse(stringDate, DateTimeFormatter.ofPattern(pattern)) - } catch (DateTimeParseException | IllegalArgumentException ignored3) {} - } - } - } - return null - } -} diff --git a/src/main/groovy/com/netgrif/application/engine/validation/models/DateTimeFieldValidation.groovy b/src/main/groovy/com/netgrif/application/engine/validation/models/DateTimeFieldValidation.groovy deleted file mode 100644 index 20d58c025c4..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/validation/models/DateTimeFieldValidation.groovy +++ /dev/null @@ -1,122 +0,0 @@ -package com.netgrif.application.engine.validation.models - -import com.netgrif.application.engine.petrinet.domain.dataset.DateField -import com.netgrif.application.engine.petrinet.domain.dataset.DateTimeField -import com.netgrif.application.engine.petrinet.domain.dataset.Field -import com.netgrif.application.engine.validation.domain.ValidationDataInput - -import java.time.DayOfWeek -import java.time.LocalDate -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter -import java.time.format.DateTimeParseException -import java.time.temporal.ChronoField - -class DateTimeFieldValidation extends AbstractFieldValidation { - -// BETWEEN = 'between' -// WORKDAY = 'workday' -// WEEKEND = 'weekend' -// REQUIRED = 'required', -// VALID_BETWEEN = 'validBetween', -// VALID_WORKDAY = 'validWorkday', -// VALID_WEEKEND = 'validWeekend' - -// between today,future -// between past,today -// between 2020-03-03,today - - public static final String FUTURE = "future" - public static final String TODAY = "today" - public static final String PAST = "past" - public static final String NOW = "now" - - - void between(ValidationDataInput validationData) { - LocalDateTime updateDate_TODAY = LocalDateTime.now() - List regex = validationData.getValidationRegex().trim().split(",") - LocalDateTime setDate = getDateTimeValue(validationData.getData()) - if (regex.size() == 2) { - def fromDate = parseStringToLocalDateTime(regex.get(0)) != null ? parseStringToLocalDateTime(regex.get(0)) : regex.get(0) - def toDate = parseStringToLocalDateTime(regex.get(1)) != null ? parseStringToLocalDateTime(regex.get(1)) : regex.get(1) - if ((fromDate == TODAY || fromDate == NOW) && toDate == FUTURE) { - if (setDate < updateDate_TODAY) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else if (fromDate == PAST && (toDate == TODAY || toDate == NOW)) { - if (setDate > updateDate_TODAY) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else if (fromDate == PAST && (toDate instanceof LocalDateTime)) { - if (setDate > toDate) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else if (fromDate == TODAY && (toDate instanceof LocalDateTime)) { - if (setDate < toDate || setDate > updateDate_TODAY) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else if ((fromDate instanceof LocalDateTime) && toDate == TODAY) { - if (setDate < fromDate || setDate > updateDate_TODAY) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else if (toDate == FUTURE && (fromDate instanceof LocalDateTime)) { - if (setDate < fromDate) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else if ((fromDate instanceof LocalDateTime) && (toDate instanceof LocalDateTime)) { - if (setDate > toDate || setDate < fromDate) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - } - - void workday(ValidationDataInput validationData) { - LocalDateTime setDate = getDateTimeValue(validationData.getData()) - if (isWeekend(setDate)) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - - void weekend(ValidationDataInput validationData) { - LocalDateTime setDate = getDateTimeValue(validationData.getData()) - if (!isWeekend(setDate)) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - - protected static boolean isWeekend(LocalDateTime day) { - DayOfWeek dayOfWeek = DayOfWeek.of(day.get(ChronoField.DAY_OF_WEEK)); - return dayOfWeek == DayOfWeek.SUNDAY || dayOfWeek == DayOfWeek.SATURDAY; - } -// TODO: release/8.0.0 Refactor, each type own validator with common functions - LocalDateTime getDateTimeValue(Field field) { - if (field instanceof DateTimeField) { - return ((DateTimeField) field).getRawValue() - } - throw new IllegalArgumentException("Cannot validate field " + field.stringId + " of type " + field.type + " with date validation") - } - - protected static LocalDateTime parseStringToLocalDateTime(String stringDate) { - if (stringDate == null) - return null - - List patterns = Arrays.asList("dd.MM.yyyy") - try { - return LocalDate.parse(stringDate, DateTimeFormatter.BASIC_ISO_DATE) - } catch (DateTimeParseException e) { - try { - return LocalDate.parse(stringDate, DateTimeFormatter.ISO_DATE) - } catch (DateTimeParseException ex) { - for (String pattern : patterns) { - try { - return LocalDate.parse(stringDate, DateTimeFormatter.ofPattern(pattern)) - } catch (DateTimeParseException | IllegalArgumentException exc) { - continue - } - } - } - } - return null - } -} diff --git a/src/main/groovy/com/netgrif/application/engine/validation/models/EnumerationFieldValidation.groovy b/src/main/groovy/com/netgrif/application/engine/validation/models/EnumerationFieldValidation.groovy deleted file mode 100644 index 265390cce75..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/validation/models/EnumerationFieldValidation.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package com.netgrif.application.engine.validation.models - -import com.netgrif.application.engine.validation.domain.ValidationDataInput - -class EnumerationFieldValidation extends AbstractFieldValidation { - -// WRONG_VALUE = 'wrongValue', -// REQUIRED = 'required' - - // TODO: release/8.0.0 should not be possible, setOption should null value if the options is no longer present - void wrongValue(ValidationDataInput validationData) { -// if (!(validationData.getData().getOptions().get(validationData.getData().getValue()))) { -// throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) -// } - } - -} diff --git a/src/main/groovy/com/netgrif/application/engine/validation/models/I18nFieldValidation.groovy b/src/main/groovy/com/netgrif/application/engine/validation/models/I18nFieldValidation.groovy deleted file mode 100644 index ae65744bb9f..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/validation/models/I18nFieldValidation.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package com.netgrif.application.engine.validation.models - -import com.netgrif.application.engine.validation.domain.ValidationDataInput - -class I18nFieldValidation extends AbstractFieldValidation { - -// TRANSLATION_REQUIRED = 'translationRequired', -// TRANSLATION_ONLY = 'translationOnly', -// REQUIRED_I18N = 'requiredI18n' - - void wrongValue(ValidationDataInput validationData) { - if (!(validationData.getData().getValue() == true)) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - -} diff --git a/src/main/groovy/com/netgrif/application/engine/validation/models/NumberFieldValidation.groovy b/src/main/groovy/com/netgrif/application/engine/validation/models/NumberFieldValidation.groovy deleted file mode 100644 index 070ed4dd80d..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/validation/models/NumberFieldValidation.groovy +++ /dev/null @@ -1,93 +0,0 @@ -package com.netgrif.application.engine.validation.models - -import com.netgrif.application.engine.validation.domain.ValidationDataInput - -class NumberFieldValidation extends AbstractFieldValidation { - static final String INF = 'inf' - -// static final String ODD = 'odd' -// static final String EVEN = 'even' -// static final String POSITIVE = 'positive' -// static final String NEGATIVE = 'negative' -// static final String DECIMAL = 'decimal' -// static final String IN_RANGE = 'inrange' -// static final String INF = 'inf' -// static final String REQUIRED = 'required' -// static final String VALID_ODD = 'validOdd' -// static final String VALID_EVEN = 'validEven' -// static final String VALID_POSITIVE = 'validPositive' -// static final String VALID_NEGATIVE = 'validNegative' -// static final String VALID_DECIMAL = 'validDecimal' -// static final String VALID_IN_RANGE = 'validInRange' - - - void odd(ValidationDataInput validationData) { - if (!(validationData.getData().getValue() == null || validationData.getData().getRawValue() == null)) { - if (validationData.getData().getRawValue() % 2 == 0) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - - void even(ValidationDataInput validationData) { - if (!(validationData.getData().getValue() == null || validationData.getData().getRawValue() == null)) { - if (validationData.getData().getRawValue() % 2 != 0) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - - void positive(ValidationDataInput validationData) { - if (!(validationData.getData().getValue() == null || validationData.getData().getRawValue() == null)) { - if (validationData.getData().getRawValue() < 0) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - - void negative(ValidationDataInput validationData) { - if (!(validationData.getData().getValue() == null || validationData.getData().getRawValue() == null)) { - - - if (validationData.getData() != null) { - if (validationData.getData().getRawValue() > 0) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - } - - void decimal(ValidationDataInput validationData) { - if (!(validationData.getData().getValue() == null || validationData.getData().getRawValue() == null)) { - if (validationData.getData().getRawValue() % 1 != 0) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - - void inrange(ValidationDataInput validationData) { - if (!(validationData.getData().getValue() == null || validationData.getData().getRawValue() == null)) { - String[] ranges = validationData.validationRegex.split(",") - if (ranges.size() == 2) { - if (ranges.any { it.toLowerCase().equals(INF) }) { - if (ranges.first().toLowerCase() != INF) { - if (validationData.getData().getRawValue() < ranges[0] as Double) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } else { - if (ranges[1].toLowerCase() != INF) { - if (validationData.getData().getRawValue() > ranges[1] as Double) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - } else { - if (validationData.getData().getRawValue() < ranges[0] as Double || validationData.getData().getRawValue() > ranges[1] as Double) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - } - } - -} diff --git a/src/main/groovy/com/netgrif/application/engine/validation/models/TextFieldValidation.groovy b/src/main/groovy/com/netgrif/application/engine/validation/models/TextFieldValidation.groovy deleted file mode 100644 index 33abd482be3..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/validation/models/TextFieldValidation.groovy +++ /dev/null @@ -1,60 +0,0 @@ -package com.netgrif.application.engine.validation.models - -import com.netgrif.application.engine.validation.domain.ValidationDataInput - -class TextFieldValidation extends AbstractFieldValidation { - - public static String telNumberRegex = '^(?:\\+?(\\d{1,3}))?([-. (]*(\\d{3})[-. )]*)?((\\d{3})[-. ]*(\\d{2,4})(?:[-.x ]*(\\d+))?)$' - public static String emailRegex = '^[a-zA-Z0-9\\._\\%\\+\\-]+@[a-zA-Z0-9\\.\\-]+\\.[a-zA-Z]{2,}$' -// REQUIRED = 'required' -// MIN_LENGTH = 'minLength' -// MAX_LENGTH = 'maxLength' -// VALID_MIN_LENGTH = 'minlength' -// VALID_MAX_LENGTH = 'maxlength' -// PATTERN = 'pattern' -// REGEX = 'regex' -// VALID_TEL_NUMBER = 'validTelNumber' -// TEL_NUMBER = 'telNumber' -// EMAIL = 'email' - - void regex(ValidationDataInput validationData) { - if (validationData.getData().getValue() != null && validationData.getData().getRawValue() != null) { - if (!(validationData.getData().getRawValue() ==~ validationData.getValidationRegex())) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - - void minlength(ValidationDataInput validationData) { - if (validationData.getData().getValue() != null && validationData.getData().getRawValue() != null) { - if (!((validationData.getData().getRawValue() as String).length() >= (validationData.getValidationRegex() as Integer))) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - - void maxlength(ValidationDataInput validationData) { - if (validationData.getData().getValue() != null && validationData.getData().getRawValue() != null) { - if ((validationData.getData().getRawValue() as String).length() > (validationData.getValidationRegex() as Integer)) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - - void telnumber(ValidationDataInput validationData) { - if (validationData.getData().getValue() != null && validationData.getData().getRawValue() != null) { - if (!(validationData.getData().getRawValue() ==~ telNumberRegex)) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - - void email(ValidationDataInput validationData) { - if (validationData.getData().getValue() != null && validationData.getData().getRawValue() != null) { - if (!(validationData.getData().getRawValue() ==~ emailRegex)) { - throw new IllegalArgumentException(validationData.getValidationMessage().getTranslation(validationData.getLocale())) - } - } - } - -} diff --git a/src/main/groovy/com/netgrif/application/engine/validation/service/ValidationService.groovy b/src/main/groovy/com/netgrif/application/engine/validation/service/ValidationService.groovy deleted file mode 100644 index 26e8b77afcc..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/validation/service/ValidationService.groovy +++ /dev/null @@ -1,75 +0,0 @@ -package com.netgrif.application.engine.validation.service - -import com.netgrif.application.engine.petrinet.domain.I18nString -import com.netgrif.application.engine.petrinet.domain.dataset.* -import com.netgrif.application.engine.validation.domain.ValidationDataInput -import com.netgrif.application.engine.validation.models.* -import com.netgrif.application.engine.validation.service.interfaces.IValidationService -import groovy.util.logging.Slf4j -import org.springframework.context.i18n.LocaleContextHolder -import org.springframework.stereotype.Service - -import java.util.stream.Collectors - -@Slf4j -@Service -class ValidationService implements IValidationService { - - @Override - void valid(Field dataField) { - if (dataField.getValidations() == null) { - return - } - dataField.getValidations().forEach(validation -> { - List rules = validation.getRule().trim().split(" ").toList() - if (rules.size() >= 1) { - AbstractFieldValidation instance = new AbstractFieldValidation() - if (dataField instanceof NumberField) { - instance = new NumberFieldValidation() - } else if (dataField instanceof TextField) { - instance = new TextFieldValidation() - } else if (dataField instanceof BooleanField) { - instance = new BooleanFieldValidation() - } else if (dataField instanceof DateField) { - instance = new DateFieldValidation() - } else if (dataField instanceof DateTimeField) { - instance = new DateTimeFieldValidation() - } else if (dataField instanceof ButtonField) { - - } else if (dataField instanceof UserField) { - - } else if (dataField instanceof DateField) { - - } else if (dataField instanceof DateTimeField) { - - } else if (dataField instanceof EnumerationField) { - - } else if (dataField instanceof EnumerationMapField) { - - } else if (dataField instanceof MultichoiceMapField) { - - } else if (dataField instanceof MultichoiceField) { - - } else if (dataField instanceof FileField) { - - } else if (dataField instanceof FileListField) { - - } else if (dataField instanceof UserListField) { - - } else if (dataField instanceof I18nField) { - - } - MetaMethod method = instance.metaClass.getMethods().find { it.name.toLowerCase() == rules.first().toLowerCase() } - if (method != null) { - I18nString validMessage = validation.getMessage() ?: new I18nString("Invalid Field value") - method.invoke(instance, new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" ")))) - } else { - log.warn("Method [" + rules.first() + "] in dataField " + dataField.getImportId() + " not found") - } - } - }) - - - } - -} diff --git a/src/main/groovy/com/netgrif/application/engine/validation/service/interfaces/IValidationService.groovy b/src/main/groovy/com/netgrif/application/engine/validation/service/interfaces/IValidationService.groovy deleted file mode 100644 index 22ed23b223c..00000000000 --- a/src/main/groovy/com/netgrif/application/engine/validation/service/interfaces/IValidationService.groovy +++ /dev/null @@ -1,8 +0,0 @@ -package com.netgrif.application.engine.validation.service.interfaces - -import com.netgrif.application.engine.petrinet.domain.dataset.Field - -interface IValidationService { - - void valid(Field dataField); -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/ApplicationEngine.java b/src/main/java/com/netgrif/application/engine/ApplicationEngine.java index df9f639a77e..5ab50e1e9d5 100644 --- a/src/main/java/com/netgrif/application/engine/ApplicationEngine.java +++ b/src/main/java/com/netgrif/application/engine/ApplicationEngine.java @@ -1,7 +1,5 @@ package com.netgrif.application.engine; -import com.netgrif.application.engine.petrinet.domain.DataGroupAlignmentConverter; -import com.netgrif.application.engine.petrinet.domain.layout.LayoutTypeConverter; import com.netgrif.application.engine.petrinet.domain.version.StringToVersionConverter; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; @@ -18,6 +16,7 @@ import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.hateoas.config.EnableHypermediaSupport; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.transaction.annotation.EnableTransactionManagement; import java.util.ArrayList; import java.util.List; @@ -25,6 +24,7 @@ @EnableCaching @EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL) @EnableGlobalMethodSecurity(prePostEnabled = true) +@EnableTransactionManagement @EnableAspectJAutoProxy @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) @EnableMongoAuditing @@ -43,8 +43,6 @@ void logRun(ProceedingJoinPoint joinPoint) throws Throwable { public MongoCustomConversions customConversions() { List> converters = new ArrayList<>(); converters.add(new StringToVersionConverter()); - converters.add(new LayoutTypeConverter()); - converters.add(new DataGroupAlignmentConverter()); return new MongoCustomConversions(converters); } diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AbstractUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/AbstractUser.java deleted file mode 100644 index 9a263e1d970..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AbstractUser.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.netgrif.application.engine.auth.domain; - -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import lombok.Getter; -import lombok.Setter; -import org.springframework.data.annotation.Transient; - -import javax.validation.constraints.NotNull; -import java.io.Serializable; -import java.util.HashSet; -import java.util.Set; - -public abstract class AbstractUser implements IUser, Serializable { - - private static final long serialVersionUID = 341922197277508726L; - - @NotNull - @Getter - @Setter - protected UserState state; - - @Getter - @Setter - protected Set authorities; - - @Getter - @Setter - protected Set processRoles; - - @Getter - @Setter - protected Set nextGroups; - - @Setter - @Getter - @Transient - protected IUser impersonated; - - public AbstractUser() { - authorities = new HashSet<>(); - nextGroups = new HashSet<>(); - processRoles = new HashSet<>(); - } - - public void addAuthority(Authority authority) { - // TODO: release/8.0.0 is this needed? - if (authorities.stream().anyMatch(it -> it.getId().equals(authority.getId()))) - return; - authorities.add(authority); - } - - public void addProcessRole(ProcessRole role) { - if (processRoles.stream().anyMatch(it -> it.getStringId().equals(role.getStringId()))) - return; - processRoles.add(role); - } - - public void removeProcessRole(ProcessRole role) { - processRoles.remove(role); - } - - public void addGroup(String groupId) { - this.nextGroups.add(groupId); - } - - public void removeGroup(String groupId) { - this.nextGroups.remove(groupId); - } - - public boolean isActive() { - return UserState.ACTIVE.equals(state) || UserState.BLOCKED.equals(state); - } - - public Author transformToAuthor() { - Author author = new Author(); - author.setId(this.getStringId()); - author.setEmail(this.getEmail()); - author.setFullName(this.getFullName()); - - return author; - } - - @Override - public boolean isImpersonating() { - return this.impersonated != null; - } - - @Override - public IUser getSelfOrImpersonated() { - return isImpersonating() ? this.impersonated : this; - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AnonymousUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/AnonymousUser.java deleted file mode 100644 index 6e062ace759..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AnonymousUser.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.netgrif.application.engine.auth.domain; - -import lombok.Data; -import org.bson.types.ObjectId; -import org.springframework.data.mongodb.core.mapping.Document; - -@Document -@Data -public class AnonymousUser extends User { - - public AnonymousUser() { - super(); - } - - public AnonymousUser(ObjectId id) { - super(id); - } - - public AnonymousUser(String email, String password, String name, String surname) { - super(email, password, name, surname); - } - - @Override - public LoggedUser transformToLoggedUser() { - LoggedUser loggedUser = new LoggedUser(this.getId().toString(), this.getEmail(), "n/a", this.getAuthorities()); - loggedUser.setFullName(this.getFullName()); - loggedUser.setAnonymous(true); - if (!this.getProcessRoles().isEmpty()) - loggedUser.parseProcessRoles(this.getProcessRoles()); - if (!this.getNextGroups().isEmpty()) - loggedUser.setGroups(this.getNextGroups()); - - return loggedUser; - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Author.java b/src/main/java/com/netgrif/application/engine/auth/domain/Author.java deleted file mode 100644 index 22a298c0ecf..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Author.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.netgrif.application.engine.auth.domain; - -import lombok.Data; - -import java.io.Serializable; - -@Data -public class Author implements Serializable { - - private static final long serialVersionUID = 5167778985918909834L; - - private String id; - private String email; - private String fullName; - - public Author() { - } - - public Author(String id, String email, String fullName) { - this.id = id; - this.email = email; - this.fullName = fullName; - } - - public static Author createAnonymizedAuthor() { - Author author = new Author(); - author.setId(""); - author.setEmail("***"); - author.setFullName("***"); - return author; - } - - @Override - public String toString() { - return "Author{" + - "id=" + id + - ", email='" + email + '\'' + - ", fullName='" + fullName + '\'' + - '}'; - } - - @Override - public Author clone() { - return new Author(this.id, this.email, this.fullName); - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java deleted file mode 100644 index bec86d7594d..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.netgrif.application.engine.auth.domain; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.Getter; -import lombok.Setter; -import org.bson.types.ObjectId; -import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; -import org.springframework.security.core.GrantedAuthority; - -import javax.validation.constraints.NotNull; -import java.util.HashSet; -import java.util.Set; - -@Document -public class Authority implements GrantedAuthority { - - public static final long serialVersionUID = 2839744057647464485L; - - public static final String PERMISSION = "PERM_"; - public static final String ROLE = "ROLE_"; - - public static final String admin = ROLE + "ADMIN"; - public static final String systemAdmin = ROLE + "SYSTEMADMIN"; - public static final String user = ROLE + "USER"; - public static final String anonymous = ROLE + "ANONYMOUS"; - - @Id - @Getter - private ObjectId id; - - @NotNull - @JsonIgnore - @Getter - @Setter - private String name; - - @JsonIgnore - @Getter - @Setter - private Set users; - - public Authority() { - } - - public Authority(String name) { - this.name = name; - } - - public static Authority createRole(String name) { - return new Authority(ROLE + name); - } - - public static Authority createPermission(String name) { - return new Authority(PERMISSION + name); - } - - public void addUser(IUser user) { - if (users == null) { - users = new HashSet<>(); - } - users.add(user.getStringId()); - } - - public String getStringId() { - return id.toString(); - } - - @Override - public String getAuthority() { - return this.name; - } - - public void setAuthority(String authority) { - this.name = authority; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Authority authority = (Authority) o; - - return name.equals(authority.name); - } - - @Override - public String toString() { - return "Authority{" + - "id=" + id + - ", name='" + name + '\'' + - '}'; - } - - @Override - public int hashCode() { - return name.hashCode(); - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/IUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/IUser.java deleted file mode 100644 index c210b61cf42..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/IUser.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.netgrif.application.engine.auth.domain; - -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; - -import java.util.Set; - -public interface IUser { - - String getStringId(); - - String getEmail(); - - void setEmail(String email); - - String getName(); - - void setName(String name); - - String getSurname(); - - void setSurname(String surname); - - String getFullName(); - - String getAvatar(); - - String getTelNumber(); - - UserState getState(); - - void setState(UserState state); - - Set getAuthorities(); - - void setAuthorities(Set authorities); - - Set getProcessRoles(); - - void setProcessRoles(Set processRoles); - - Set getNextGroups(); - - void setNextGroups(Set nextGroups); - - void addGroup(String groupId); - - void removeGroup(String groupId); - - void addAuthority(Authority authority); - - void addProcessRole(ProcessRole role); - - void removeProcessRole(ProcessRole role); - - LoggedUser transformToLoggedUser(); - - Author transformToAuthor(); - - boolean isActive(); - - boolean isImpersonating(); - - IUser getSelfOrImpersonated(); - - IUser getImpersonated(); - - void setImpersonated(IUser user); - -} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java deleted file mode 100644 index 7a4eb57c8e3..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.netgrif.application.engine.auth.domain; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import lombok.Getter; -import lombok.Setter; -import org.bson.types.ObjectId; -import org.springframework.security.core.GrantedAuthority; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import java.util.stream.Collectors; - -@JsonInclude(JsonInclude.Include.NON_NULL) -public class LoggedUser extends org.springframework.security.core.userdetails.User { - - public static final long serialVersionUID = 3031325636490953409L; - - @Getter - @Setter - protected String id; - - @Getter - @Setter - protected String fullName; - - @Getter - @Setter - protected Set groups; - - @Getter - @Setter - protected Set processRoles; - - @Getter - @Setter - protected boolean anonymous; - - @Getter - private LoggedUser impersonated; - - public LoggedUser(String id, String username, String password, Collection authorities) { - super(username, password, authorities); - this.id = id; - this.processRoles = new HashSet<>(); - this.groups = new HashSet<>(); - } - - public void parseProcessRoles(Set processRoles) { - processRoles.forEach(role -> this.processRoles.add(role.getStringId())); - } - - public boolean isAdmin() { - return getAuthorities().contains(new Authority(Authority.admin)); - } - - public String getEmail() { - return getUsername(); - } - - public IUser transformToUser() { - User user = new User(new ObjectId(this.id)); - user.setEmail(getUsername()); - String[] names = this.fullName.split(" "); - user.setName(names[0]); - user.setSurname(names[1]); - user.setPassword(getPassword()); - user.setState(UserState.ACTIVE); - user.setAuthorities(getAuthorities().stream().map(a -> ((Authority) a)).collect(Collectors.toSet())); - user.setNextGroups(groups.stream().map(String::new).collect(Collectors.toSet())); - user.setProcessRoles(processRoles.stream().map(roleId -> { - ProcessRole role = new ProcessRole(); - role.setId(roleId); - return role; - }).collect(Collectors.toSet())); - if (this.isImpersonating()) { - user.setImpersonated(this.getImpersonated().transformToUser()); - } - return user; - } - - public AnonymousUser transformToAnonymousUser() { - AnonymousUser anonym = new AnonymousUser(new ObjectId(this.id)); - anonym.setEmail(getUsername()); - anonym.setName("Anonymous"); - anonym.setSurname("User"); - anonym.setPassword("n/a"); - anonym.setState(UserState.ACTIVE); - anonym.setAuthorities(getAuthorities().stream().map(a -> ((Authority) a)).collect(Collectors.toSet())); - anonym.setNextGroups(groups.stream().map(String::new).collect(Collectors.toSet())); - anonym.setProcessRoles(processRoles.stream().map(roleId -> { - ProcessRole role = new ProcessRole(); - role.setId(roleId); - return role; - }).collect(Collectors.toSet())); - return anonym; - } - - public void impersonate(LoggedUser toImpersonate) { - this.impersonated = toImpersonate; - } - - public void clearImpersonated() { - this.impersonated = null; - } - - public boolean isImpersonating() { - return this.impersonated != null; - } - - @JsonIgnore - public LoggedUser getSelfOrImpersonated() { - return this.isImpersonating() ? this.impersonated : this; - } - - @Override - public String toString() { - return "LoggedUser{" + - "id=" + id + - ", fullName='" + fullName + '\'' + - ", groups=" + groups + - ", processRoles=" + processRoles + - ", impersonated=" + impersonated + - '}'; - } - - public Author transformToAuthor() { - Author author = new Author(); - author.setId(this.id); - author.setEmail(getUsername()); - author.setFullName(this.fullName); - - return author; - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/RegisteredUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/RegisteredUser.java deleted file mode 100644 index e64e2406230..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/RegisteredUser.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.netgrif.application.engine.auth.domain; - -import java.time.LocalDateTime; - -public interface RegisteredUser extends IUser { - - String getToken(); - - void setToken(String token); - - String getPassword(); - - void setPassword(String password); - - void setExpirationDate(LocalDateTime expirationDate); -} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/User.java b/src/main/java/com/netgrif/application/engine/auth/domain/User.java deleted file mode 100644 index 041f4295243..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/User.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.netgrif.application.engine.auth.domain; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import lombok.Getter; -import lombok.Setter; -import org.bson.types.ObjectId; -import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.index.Indexed; -import org.springframework.data.mongodb.core.mapping.Document; - -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; -import java.util.HashSet; - -@Document -public class User extends AbstractUser implements RegisteredUser { - - public static final String UNKNOWN = "unknown"; - - @Id - @Getter - protected ObjectId id; - - @NotNull - @Getter - @Setter - @Indexed(unique = true) - protected String email; - - @Getter - @Setter - protected String telNumber; - - @Getter - @Setter - protected String avatar; - - @JsonIgnore - @Getter - @Setter - protected String password; - - @NotNull - @Getter - @Setter - @Indexed - protected String name; - - @NotNull - @Getter - @Setter - @Indexed - protected String surname; - - @Getter - @Setter - protected String token; - - @Getter - @Setter - protected LocalDateTime expirationDate; - - public User() { - super(); - } - - public User(ObjectId id) { - this(); - this.id = id; - nextGroups = new HashSet<>(); - } - - public User(User user) { - this.id = user.getId(); - this.email = user.getEmail(); - this.surname = user.getSurname(); - this.name = user.getName(); - this.state = user.getState(); - } - - public User(String email, String password, String name, String surname) { - this(); - this.email = email; - this.password = password; - this.name = name; - this.surname = surname; - this.nextGroups = new HashSet<>(); - } - - public String getFullName() { - return name + " " + surname; - } - - @JsonIgnore - public String getStringId() { - return id.toString(); - } - - public LoggedUser transformToLoggedUser() { - LoggedUser loggedUser = new LoggedUser(this.getId().toString(), this.getEmail(), this.getPassword(), this.getAuthorities()); - loggedUser.setFullName(this.getFullName()); - loggedUser.setAnonymous(false); - if (!this.getProcessRoles().isEmpty()) { - loggedUser.parseProcessRoles(this.getProcessRoles()); - } - loggedUser.setGroups(this.getNextGroups()); - if (this.isImpersonating()) { - loggedUser.impersonate(this.getImpersonated().transformToLoggedUser()); - } - return loggedUser; - } - - @Override - @JsonIgnore - public IUser getSelfOrImpersonated() { - return super.getSelfOrImpersonated(); - } - - @Override - public String toString() { - return "User{" + - "id=" + id + - ", email='" + email + '\'' + - ", telNumber='" + telNumber + '\'' + - ", avatar='" + avatar + '\'' + - ", name='" + name + '\'' + - ", surname='" + surname + '\'' + - ", state=" + state + - ", token='" + token + '\'' + - ", expirationDate=" + expirationDate + - ", authorities=" + authorities + - ", processRoles=" + processRoles + - ", groups=" + nextGroups + - '}'; - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/UserProcessRole.java b/src/main/java/com/netgrif/application/engine/auth/domain/UserProcessRole.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/UserProperties.java b/src/main/java/com/netgrif/application/engine/auth/domain/UserProperties.java deleted file mode 100644 index 3b756a15a6b..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/UserProperties.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.netgrif.application.engine.auth.domain; - -public class UserProperties { - public static final String ANONYMOUS_AUTH_KEY = "anonymousUser"; -} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/UserState.java b/src/main/java/com/netgrif/application/engine/auth/domain/UserState.java deleted file mode 100644 index 2655b9fde43..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/UserState.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.netgrif.application.engine.auth.domain; - -public enum UserState { - ACTIVE, - BLOCKED, - INVITED -} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/repositories/AuthorityRepository.java b/src/main/java/com/netgrif/application/engine/auth/domain/repositories/AuthorityRepository.java deleted file mode 100644 index 9224926803e..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/repositories/AuthorityRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.netgrif.application.engine.auth.domain.repositories; - -import com.netgrif.application.engine.auth.domain.Authority; -import org.bson.types.ObjectId; -import org.springframework.data.mongodb.repository.MongoRepository; -import org.springframework.data.querydsl.QuerydslPredicateExecutor; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public interface AuthorityRepository extends MongoRepository, QuerydslPredicateExecutor { - - Authority findByName(String name); - - List findAllByNameStartsWith(String prefix); - - List findAllByIdIn(List ids); -} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/repositories/UserRepository.java b/src/main/java/com/netgrif/application/engine/auth/domain/repositories/UserRepository.java deleted file mode 100644 index 9821b518b08..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/repositories/UserRepository.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.netgrif.application.engine.auth.domain.repositories; - -import com.netgrif.application.engine.auth.domain.QUser; -import com.netgrif.application.engine.auth.domain.User; -import com.netgrif.application.engine.auth.domain.UserState; -import org.bson.types.ObjectId; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.mongodb.repository.MongoRepository; -import org.springframework.data.querydsl.QuerydslPredicateExecutor; -import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer; -import org.springframework.data.querydsl.binding.QuerydslBindings; -import org.springframework.stereotype.Repository; - -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Set; - -@Repository -public interface UserRepository extends MongoRepository, QuerydslPredicateExecutor, QuerydslBinderCustomizer { - - Page findAllByIdInAndState(Set ids, UserState state, Pageable pageable); - - User findByEmail(String email); - - List findAllByStateAndExpirationDateBefore(UserState userState, LocalDateTime dateTime); - - Page findDistinctByStateAndProcessRoles_IdIn(UserState state, List roleId, Pageable pageable); - - List findAllByProcessRoles_IdIn(List roleId); - - List removeAllByStateAndExpirationDateBefore(UserState state, LocalDateTime dateTime); - - List findAllByIdIn(Set ids); - - boolean existsByEmail(String email); - - @Override - default void customize(QuerydslBindings bindings, QUser qUser) { - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/repositories/UserRepositoryImpl.java b/src/main/java/com/netgrif/application/engine/auth/domain/repositories/UserRepositoryImpl.java deleted file mode 100644 index 849accdd70f..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/repositories/UserRepositoryImpl.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.netgrif.application.engine.auth.domain.repositories; - -import org.springframework.stereotype.Repository; - -@Repository("userRepository") -public abstract class UserRepositoryImpl implements UserRepository { -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java deleted file mode 100644 index bb98acbcbec..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.netgrif.application.engine.auth.service; - -import com.netgrif.application.engine.auth.domain.*; -import com.netgrif.application.engine.auth.domain.repositories.UserRepository; -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; -import com.netgrif.application.engine.security.service.ISecurityContextService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; -import org.springframework.security.core.context.SecurityContextHolder; - -import java.util.HashSet; -import java.util.List; -import java.util.stream.Collectors; - -import static com.netgrif.application.engine.startup.SystemUserRunner.*; - -public abstract class AbstractUserService implements IUserService { - - @Autowired - protected IAuthorityService authorityService; - - @Autowired - protected IProcessRoleService processRoleService; - - - @Autowired - protected INextGroupService groupService; - - @Autowired - protected UserRepository repository; - - @Autowired - private ISecurityContextService securityContextService; - - @Override - public void addDefaultRole(IUser user) { - user.addProcessRole(processRoleService.defaultRole()); - } - - @Override - public void addDefaultAuthorities(IUser user) { - if (user.getAuthorities().isEmpty()) { - HashSet authorities = new HashSet<>(); - authorities.add(authorityService.getOrCreate(Authority.user)); - user.setAuthorities(authorities); - } - } - - @Override - public IUser assignAuthority(String userId, String authorityId) { - IUser user = resolveById(userId); - Authority authority = authorityService.getOne(authorityId); - user.addAuthority(authority); - authority.addUser(user); - - return save(user); - } - - @Override - public LoggedUser getAnonymousLogged() { - if (SecurityContextHolder.getContext().getAuthentication().getPrincipal().equals(UserProperties.ANONYMOUS_AUTH_KEY)) { - getLoggedUser().transformToLoggedUser(); - } - return (LoggedUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - } - - @Override - public IUser addRole(IUser user, String roleStringId) { - ProcessRole role = processRoleService.findById(roleStringId); - user.addProcessRole(role); - securityContextService.saveToken(user.getStringId()); - securityContextService.reloadSecurityContext(user.transformToLoggedUser()); - return save(user); - } - - /** - * @param user - * @param roleStringId - * @return - * @deprecated use {@link AbstractUserService#removeRole(IUser, ProcessRole)} instead - */ - @Override - @Deprecated(since = "6.2.0") - public IUser removeRole(IUser user, String roleStringId) { - return removeRole(user, processRoleService.findByImportId(roleStringId)); - } - - protected IUser removeRole(IUser user, ProcessRole role) { - user.removeProcessRole(role); - securityContextService.saveToken(user.getStringId()); - securityContextService.reloadSecurityContext(user.transformToLoggedUser()); - return save(user); - } - - @Override - public void removeRoleOfDeletedPetriNet(PetriNet net) { - List users = findAllByProcessRoles(net.getRoles().keySet()); - users.forEach(u -> { - net.getRoles().forEach((k, role) -> removeRole(u, role)); - }); - } - - @Override - public IUser createSystemUser() { - User system = repository.findByEmail(SYSTEM_USER_EMAIL); - if (system == null) { - system = new User(SYSTEM_USER_EMAIL, "n/a", SYSTEM_USER_NAME, SYSTEM_USER_SURNAME); - system.setState(UserState.ACTIVE); - repository.save(system); - } - return system; - } - - public Page changeType(Page users, Pageable pageable) { - return new PageImpl<>(changeType(users.getContent()), pageable, users.getTotalElements()); - } - - public List changeType(List users) { - return users.stream().map(IUser.class::cast).collect(Collectors.toList()); - } - - @Override - public IUser getUserFromLoggedUser(LoggedUser loggedUser) { - IUser user = resolveById(loggedUser.getId()); - IUser fromLogged = loggedUser.transformToUser(); - user.setImpersonated(fromLogged.getImpersonated()); - return user; - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java deleted file mode 100644 index ce89b439419..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.netgrif.application.engine.auth.service; - -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.repositories.AuthorityRepository; -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; -import org.bson.types.ObjectId; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -@Service -public class AuthorityService implements IAuthorityService { - - private final AuthorityRepository repository; - - public AuthorityService(AuthorityRepository repository) { - this.repository = repository; - } - - @Override - public List findAll() { - return repository.findAll(); - } - - @Override - @Transactional - public Authority getOrCreate(String name) { - Authority authority = repository.findByName(name); - if (authority == null) { - authority = repository.save(new Authority(name)); - } - return authority; - } - - @Override - public Authority getOrCreatePermission(String name) { - return getOrCreate(Authority.PERMISSION + name); - } - - @Override - public Authority getOrCreateRole(String name) { - return getOrCreate(Authority.ROLE + name); - } - - @Override - public List getAllPermissions() { - return repository.findAllByNameStartsWith(Authority.PERMISSION); - } - - @Override - public List getAllRoles() { - return repository.findAllByNameStartsWith(Authority.ROLE); - } - - @Override - public Authority getOne(String id) { - Optional authority = repository.findById(id); - if (authority.isEmpty()) { - throw new IllegalArgumentException("Could not find authority with id [" + id + "]"); - } - return authority.get(); - } - - @Override - public List findAllByIds(List ids) { - return repository.findAllByIdIn(ids.stream().map(ObjectId::new).collect(Collectors.toList())); - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorizationService.java deleted file mode 100644 index 4050f20a223..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorizationService.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.netgrif.application.engine.auth.service; - -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IAuthorizationService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class AuthorizationService implements IAuthorizationService { - - @Autowired - private IUserService userService; - - @Override - public boolean hasAuthority(String authority) { - LoggedUser loggedUser = userService.getLoggedUserFromContext().getSelfOrImpersonated(); - return loggedUser.getAuthorities().stream().anyMatch(it -> it.getAuthority().equals(Authority.ROLE + authority)); - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/InvalidUserTokenException.java b/src/main/java/com/netgrif/application/engine/auth/service/InvalidUserTokenException.java deleted file mode 100644 index c01c9253b9a..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/InvalidUserTokenException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.netgrif.application.engine.auth.service; - -public class InvalidUserTokenException extends Exception { - - public InvalidUserTokenException(String token) { - super("Token " + token + " has invalid format"); - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/LdapUserDetailsService.java b/src/main/java/com/netgrif/application/engine/auth/service/LdapUserDetailsService.java deleted file mode 100644 index 7d7c926346a..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/LdapUserDetailsService.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.netgrif.application.engine.auth.service; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.domain.UserState; -import com.netgrif.application.engine.ldap.domain.LdapUser; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.security.core.userdetails.UsernameNotFoundException; - -@ConditionalOnExpression("${nae.ldap.enabled:false}") -public class LdapUserDetailsService extends UserDetailsServiceImpl { - - @Override - protected LoggedUser getLoggedUser(String email) throws UsernameNotFoundException { - IUser user = userRepository.findByEmail(email); - if (user == null) { - throw new UsernameNotFoundException("No user was found for login: " + email); - } else if (user.getState() != UserState.ACTIVE) { - throw new UsernameNotFoundException("User with login " + email + " cannot be logged in!"); - } else if (user instanceof LdapUser) { - throw new UsernameNotFoundException("Ldap has not verified the user " + email + "!"); - } - - return user.transformToLoggedUser(); - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/RegistrationService.java b/src/main/java/com/netgrif/application/engine/auth/service/RegistrationService.java deleted file mode 100644 index 85b33d5eba2..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/RegistrationService.java +++ /dev/null @@ -1,244 +0,0 @@ -package com.netgrif.application.engine.auth.service; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.RegisteredUser; -import com.netgrif.application.engine.auth.domain.User; -import com.netgrif.application.engine.auth.domain.UserState; -import com.netgrif.application.engine.auth.domain.repositories.UserRepository; -import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.auth.web.requestbodies.NewUserRequest; -import com.netgrif.application.engine.auth.web.requestbodies.RegistrationRequest; -import com.netgrif.application.engine.configuration.properties.ServerAuthProperties; -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.math.BigInteger; -import java.security.SecureRandom; -import java.time.LocalDateTime; -import java.util.Base64; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; - -@Slf4j -@Service -public class RegistrationService implements IRegistrationService { - - @Autowired - protected BCryptPasswordEncoder bCryptPasswordEncoder; - - @Autowired - private UserRepository userRepository; - - @Autowired - private IUserService userService; - - @Autowired - private INextGroupService groupService; - - @Autowired - private IProcessRoleService processRole; - - @Autowired - private ServerAuthProperties serverAuthProperties; - - @Override - @Transactional - @Scheduled(cron = "0 0 1 * * *") - public void removeExpiredUsers() { - log.info("Removing expired unactivated invited users"); - List expired = userRepository.removeAllByStateAndExpirationDateBefore(UserState.INVITED, LocalDateTime.now()); - log.info("Removed " + expired.size() + " unactivated users"); - } - - @Override - @Transactional - @Scheduled(cron = "0 0 1 * * *") - public void resetExpiredToken() { - log.info("Resetting expired user tokens"); - List users = userRepository.findAllByStateAndExpirationDateBefore(UserState.BLOCKED, LocalDateTime.now()); - if (users == null || users.isEmpty()) { - log.info("There are none expired tokens. Everything is awesome."); - return; - } - - users.forEach(user -> { - user.setToken(null); - user.setExpirationDate(null); - }); - users = userRepository.saveAll(users); - log.info("Reset " + users.size() + " expired user tokens"); - } - - @Override - public void changePassword(RegisteredUser user, String newPassword) { - user.setPassword(newPassword); - encodeUserPassword(user); - userService.save(user); - log.info("Changed password for user " + user.getEmail() + "."); - } - - @Override - public boolean verifyToken(String token) { - try { - log.info("Verifying token:" + token); - String[] tokenParts = decodeToken(token); - User user = userRepository.findByEmail(tokenParts[0]); - return user != null && Objects.equals(user.getToken(), tokenParts[1]) && user.getExpirationDate().isAfter(LocalDateTime.now()); - } catch (InvalidUserTokenException e) { - log.error(e.getMessage()); - return false; - } - } - - @Override - public void encodeUserPassword(RegisteredUser user) { - String pass = user.getPassword(); - if (pass == null) { - throw new IllegalArgumentException("User has no password"); - } - user.setPassword(bCryptPasswordEncoder.encode(pass)); - } - - @Override - public boolean stringMatchesUserPassword(RegisteredUser user, String passwordToCompare) { - return bCryptPasswordEncoder.matches(passwordToCompare, user.getPassword()); - } - - @Override - @Transactional - public User createNewUser(NewUserRequest newUser) { - User user; - if (userRepository.existsByEmail(newUser.email)) { - user = userRepository.findByEmail(newUser.email); - if (user.isActive()) { - return null; - } - log.info("Renewing old user [" + newUser.email + "]"); - } else { - user = new User(newUser.email, null, User.UNKNOWN, User.UNKNOWN); - log.info("Creating new user [" + newUser.email + "]"); - } - user.setToken(generateTokenKey()); - user.setPassword(""); - user.setExpirationDate(generateExpirationDate()); - user.setState(UserState.INVITED); - userService.addDefaultAuthorities(user); - - if (newUser.processRoles != null && !newUser.processRoles.isEmpty()) { - user.setProcessRoles(new HashSet<>(processRole.findByIds(newUser.processRoles))); - } - userService.addDefaultRole(user); - user = userRepository.save(user); - - if (newUser.groups != null && !newUser.groups.isEmpty()) { - for (String group : newUser.groups) { - groupService.addUser((IUser) user, group); - } - } - - return userRepository.save(user); - } - - @Override - public RegisteredUser registerUser(RegistrationRequest registrationRequest) throws InvalidUserTokenException { - String email = decodeToken(registrationRequest.token)[0]; - log.info("Registering user " + email); - RegisteredUser user = userRepository.findByEmail(email); - if (user == null) { - return null; - } - - user.setName(registrationRequest.name); - user.setSurname(registrationRequest.surname); - user.setPassword(registrationRequest.password); - - user.setToken(null); - user.setExpirationDate(null); - user.setState(UserState.ACTIVE); - - return (RegisteredUser) userService.saveNewAndAuthenticate(user); - } - - @Override - public RegisteredUser resetPassword(String email) { - log.info("Resetting password of " + email); - User user = userRepository.findByEmail(email); - if (user == null || !user.isActive()) { - String state = user == null ? "Non-existing" : "Inactive"; - log.info(state + " user [" + email + "] tried to reset his password"); - return null; - } - - user.setState(UserState.BLOCKED); - user.setPassword(null); - user.setToken(generateTokenKey()); - user.setExpirationDate(generateExpirationDate()); - return (RegisteredUser) userService.save(user); - } - - @Override - public RegisteredUser recover(String email, String newPassword) { - log.info("Recovering user " + email); - User user = userRepository.findByEmail(email); - if (user == null) { - return null; - } - user.setState(UserState.ACTIVE); - user.setPassword(newPassword); - encodeUserPassword(user); - user.setToken(null); - user.setExpirationDate(null); - - return (RegisteredUser) userService.save(user); - } - - @Override - public String generateTokenKey() { - return new BigInteger(256, new SecureRandom()).toString(32); - } - - @Override - public String[] decodeToken(String token) throws InvalidUserTokenException { - if (token == null || token.isEmpty()) { - throw new InvalidUserTokenException(token); - } - byte[] decodedBytes; - - try { - decodedBytes = Base64.getDecoder().decode(token); - } catch (IllegalArgumentException exception) { - throw new InvalidUserTokenException(token); - } - String decodedString = new String(decodedBytes); - String[] parts = decodedString.split(":"); - - if (parts.length != 2 || !parts[0].contains("@")) { - throw new InvalidUserTokenException(token); - } - - return parts; - } - - @Override - public String encodeToken(String email, String tokenKey) { - return Base64.getEncoder().encodeToString((email + ":" + tokenKey).getBytes()); - } - - @Override - public LocalDateTime generateExpirationDate() { - return LocalDateTime.now().plusDays(serverAuthProperties.getTokenValidityPeriod()); - } - - @Override - public boolean isPasswordSufficient(String password) { - return password.length() >= serverAuthProperties.getMinimalPasswordLength(); - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/UserDetailsServiceImpl.java b/src/main/java/com/netgrif/application/engine/auth/service/UserDetailsServiceImpl.java deleted file mode 100644 index 4a64ee1b815..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/UserDetailsServiceImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.netgrif.application.engine.auth.service; - -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.domain.User; -import com.netgrif.application.engine.auth.domain.UserState; -import com.netgrif.application.engine.auth.domain.repositories.UserRepository; -import com.netgrif.application.engine.auth.service.interfaces.ILoginAttemptService; -import com.netgrif.application.engine.event.events.user.UserLoginEvent; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.servlet.http.HttpServletRequest; - -@Slf4j -@Service -public class UserDetailsServiceImpl implements UserDetailsService { - - @Autowired - protected UserRepository userRepository; - - @Autowired - protected ApplicationEventPublisher publisher; - - @Autowired - protected ILoginAttemptService loginAttemptService; - - @Autowired - protected HttpServletRequest request; - - @Override - @Transactional(readOnly = true) - public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { - String ip = getClientIP(); - if (loginAttemptService.isBlocked(ip)) { - log.info("User " + email + " with IP Address " + ip + " is blocked."); - throw new RuntimeException("blocked"); - } - - LoggedUser loggedUser = getLoggedUser(email); - - publisher.publishEvent(new UserLoginEvent(loggedUser)); - - return loggedUser; - } - - protected LoggedUser getLoggedUser(String email) throws UsernameNotFoundException { - User user = userRepository.findByEmail(email); - if (user == null) - throw new UsernameNotFoundException("No user was found for login: " + email); - if (user.getPassword() == null || user.getState() != UserState.ACTIVE) - throw new UsernameNotFoundException("User with login " + email + " cannot be logged in!"); - - return user.transformToLoggedUser(); - } - - - protected String getClientIP() { - String xfHeader = request.getHeader("X-Forwarded-For"); - if (xfHeader == null) { - return request.getRemoteAddr(); - } - return xfHeader.split(",")[0]; - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java deleted file mode 100755 index 32b47ba5cac..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java +++ /dev/null @@ -1,361 +0,0 @@ -package com.netgrif.application.engine.auth.service; - -import com.netgrif.application.engine.auth.domain.*; -import com.netgrif.application.engine.auth.domain.repositories.AuthorityRepository; -import com.netgrif.application.engine.auth.domain.repositories.UserRepository; -import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; -import com.netgrif.application.engine.auth.web.requestbodies.UpdateUserRequest; -import com.netgrif.application.engine.event.events.user.UserRegistrationEvent; -import com.netgrif.application.engine.orgstructure.groups.config.GroupConfigurationProperties; -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; -import com.netgrif.application.engine.startup.SystemUserRunner; -import com.netgrif.application.engine.workflow.service.interfaces.IFilterImportExportService; -import com.querydsl.core.types.dsl.BooleanExpression; -import org.bson.types.ObjectId; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; - -import java.util.*; -import java.util.stream.Collectors; - -public class UserService extends AbstractUserService { - - @Autowired - protected UserRepository userRepository; - - @Autowired - protected AuthorityRepository authorityRepository; - - @Autowired - protected IProcessRoleService processRoleService; - - @Autowired - protected ApplicationEventPublisher publisher; - - @Autowired - protected INextGroupService groupService; - - @Autowired - protected IRegistrationService registrationService; - - @Autowired - private GroupConfigurationProperties groupProperties; - - @Autowired - private IFilterImportExportService filterImportExportService; - - // TODO: release/8.0.0 cleanup, remove boolean params - - @Override - public IUser saveNewAndAuthenticate(IUser user) { - return saveNew(user, true); - } - - @Override - public IUser saveNew(IUser user) { - return saveNew(user, false); - } - - private IUser saveNew(IUser user, boolean ignored) { - registrationService.encodeUserPassword((RegisteredUser) user); - addDefaultRole(user); - addDefaultAuthorities(user); - - User savedUser = userRepository.save((User) user); - filterImportExportService.createFilterImport(user); - filterImportExportService.createFilterExport(user); - - if (groupProperties.isDefaultEnabled()) { - groupService.createGroup(user); - } - if (groupProperties.isSystemEnabled()) { - groupService.addUserToDefaultGroup(user); - } - publisher.publishEvent(new UserRegistrationEvent(savedUser)); - - return savedUser; - } - - @Override - public AnonymousUser saveNewAnonymous(AnonymousUser user) { - addAnonymousRole(user); - addAnonymousAuthorities(user); - - return userRepository.save(user); - } - - @Override - public User update(IUser user, UpdateUserRequest updates) { - User dbUser = (User) user; - if (updates.telNumber != null) { - dbUser.setTelNumber(updates.telNumber); - } - if (updates.avatar != null) { - dbUser.setAvatar(updates.avatar); - } - if (updates.name != null) { - dbUser.setName(updates.name); - } - if (updates.surname != null) { - dbUser.setSurname(updates.surname); - } - dbUser = userRepository.save(dbUser); - return dbUser; - } - - public void addDefaultRole(User user) { - user.addProcessRole(processRoleService.defaultRole()); - } - - public void addAnonymousRole(User user) { - user.addProcessRole(processRoleService.anonymousRole()); - } - - public void addDefaultAuthorities(User user) { - if (!user.getAuthorities().isEmpty()) { - return; - } - HashSet authorities = new HashSet<>(); - authorities.add(authorityRepository.findByName(Authority.user)); - user.setAuthorities(authorities); - } - - public void addAnonymousAuthorities(User user) { - if (!user.getAuthorities().isEmpty()) { - return; - } - HashSet authorities = new HashSet<>(); - authorities.add(authorityRepository.findByName(Authority.anonymous)); - user.setAuthorities(authorities); - } - - @Override - public IUser findByAuth(Authentication auth) { - return findByEmail(auth.getName()); - } - - @Override - public IUser save(IUser user) { - return userRepository.save((User) user); - } - - @Override - public IUser findById(String id) { - Optional user = userRepository.findById(id); - if (user.isEmpty()) { - throw new IllegalArgumentException("Could not find user with id [" + id + "]"); - } - return user.get(); - } - - @Override - public boolean existsById(String id) { - return userRepository.existsById(id); - } - - @Override - public IUser resolveById(String id) { - return findById(id); - } - - @Override - public IUser findByEmail(String email) { - return userRepository.findByEmail(email); - } - - @Override - public IUser findAnonymousByEmail(String email) { - return findByEmail(email); - } - - - @Override - public List findAll() { - return changeType(userRepository.findAll()); - - } - - @Override - public Page findAllCoMembers(LoggedUser loggedUser, Pageable pageable) { - // TODO: 8/27/18 make all pageable - Set members = groupService.getAllCoMembers(loggedUser.getSelfOrImpersonated().transformToUser()); - members.add(loggedUser.getSelfOrImpersonated().getId()); - Set objMembers = members.stream().map(ObjectId::new).collect(Collectors.toSet()); - return changeType(userRepository.findAllByIdInAndState(objMembers, UserState.ACTIVE, pageable), pageable); - } - - @Override - public Page searchAllCoMembers(String query, LoggedUser loggedUser, Pageable pageable) { - Set members = groupService.getAllCoMembers(loggedUser.getSelfOrImpersonated().transformToUser()); - members.add(loggedUser.getSelfOrImpersonated().getId()); - - return changeType(userRepository.findAll(buildPredicate(members.stream().map(ObjectId::new) - .collect(Collectors.toSet()), query), pageable), pageable); - - } - - @Override - public Page searchAllCoMembers(String query, List roleIds, List negateRoleIds, LoggedUser loggedUser, Pageable pageable) { - if ((roleIds == null || roleIds.isEmpty()) && (negateRoleIds == null || negateRoleIds.isEmpty())) - return searchAllCoMembers(query, loggedUser, pageable); - - if (negateRoleIds == null) { - negateRoleIds = new ArrayList<>(); - } - - - Set members = groupService.getAllCoMembers(loggedUser.getSelfOrImpersonated().transformToUser()); - members.add(loggedUser.getSelfOrImpersonated().getId()); - BooleanExpression predicate = buildPredicate(members.stream().map(ObjectId::new).collect(Collectors.toSet()), query); - if (!(roleIds == null || roleIds.isEmpty())) { - predicate = predicate.and(QUser.user.processRoles.any().id.in(roleIds)); - } - predicate = predicate.and(QUser.user.processRoles.any().id.in(negateRoleIds).not()); - Page users = userRepository.findAll(predicate, pageable); - - return changeType(users, pageable); - } - - private BooleanExpression buildPredicate(Set members, String query) { - BooleanExpression predicate = QUser.user - .id.in(members) - .and(QUser.user.state.eq(UserState.ACTIVE)); - for (String word : query.split(" ")) { - predicate = predicate - .andAnyOf(QUser.user.email.containsIgnoreCase(word), - QUser.user.name.containsIgnoreCase(word), - QUser.user.surname.containsIgnoreCase(word)); - } - return predicate; - } - - @Override - public Page findAllActiveByProcessRoles(Set roleIds, Pageable pageable) { - Page users = userRepository.findDistinctByStateAndProcessRoles_IdIn(UserState.ACTIVE, new ArrayList<>(roleIds), pageable); - return changeType(users, pageable); - } - - @Override - public List findAllByProcessRoles(Set roleIds) { - List users = userRepository.findAllByProcessRoles_IdIn(new ArrayList<>(roleIds)); - return changeType(users); - } - - @Override - public List findAllByIds(Set ids) { - List users = userRepository.findAllByIdIn(ids.stream().map(ObjectId::new).collect(Collectors.toSet())); - return changeType(users); - } - - @Override - public IUser assignAuthority(String userId, String authorityId) { - Optional user = userRepository.findById(userId); - Optional authority = authorityRepository.findById(authorityId); - - if (user.isEmpty()) { - throw new IllegalArgumentException("Could not find user with id [" + userId + "]"); - } - if (authority.isEmpty()) { - throw new IllegalArgumentException("Could not find authority with id [" + authorityId + "]"); - } - - user.get().addAuthority(authority.get()); - authority.get().addUser(user.get()); - - return userRepository.save(user.get()); - } - - @Override - public IUser getLoggedOrSystem() { - try { - if (SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof String) { - return getSystem(); - } - return getLoggedUser(); - } catch (NullPointerException e) { - return getSystem(); - } - } - - @Override - public IUser getSystem() { - IUser system = userRepository.findByEmail(SystemUserRunner.SYSTEM_USER_EMAIL); - system.setProcessRoles(new HashSet<>(processRoleService.findAll())); - return system; - } - - @Override - public IUser getLoggedUser() { - LoggedUser loggedUser = getLoggedUserFromContext(); - if (!loggedUser.isAnonymous()) { - IUser user = findByEmail(loggedUser.getEmail()); - if (loggedUser.isImpersonating()) { - // cannot be simply reloaded from DB, impersonated user holds a subset of roles and authorities. - // this reloads the impersonated user's roles as they are not complete (LoggedUser creates incomplete ProcessRole objects) - IUser impersonated = loggedUser.getImpersonated().transformToUser(); - impersonated.setProcessRoles(processRoleService.findByIds(loggedUser.getImpersonated().getProcessRoles())); - user.setImpersonated(impersonated); - } - return user; - } - return loggedUser.transformToAnonymousUser(); - } - - @Override - public LoggedUser getAnonymousLogged() { - if (SecurityContextHolder.getContext().getAuthentication().getPrincipal().equals(UserProperties.ANONYMOUS_AUTH_KEY)) { - return getLoggedUser().transformToLoggedUser(); - } - return getLoggedUserFromContext(); - } - - @Override - public LoggedUser getLoggedUserFromContext() { - return (LoggedUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - } - -// @Override -// public IUser addRole(IUser user, String roleStringId) { -// ProcessRole role = processRoleService.findById(roleStringId); -// user.addProcessRole(role); -// return userRepository.save(user); -// } -// -// @Override -// public IUser removeRole(IUser user, String roleStringId) { -// ProcessRole role = processRoleService.findByImportId(roleStringId); -// user.removeProcessRole(role); -// return userRepository.save(user); -// } - - @Override - public void deleteUser(IUser user) { - User dbUser = (User) user; - if (userRepository.findById(dbUser.getStringId()).isEmpty()) { - throw new IllegalArgumentException("Could not find user with id [" + dbUser.getId() + "]"); - } - userRepository.delete(dbUser); - } - - -/* private User loadProcessRoles(User user) { - if (user == null) - return null; - user.setProcessRoles(processRoleRepository.findAllById(user.getUserProcessRoles() - .stream().map(UserProcessRole::getRoleId).collect(Collectors.toList()))); - return user; - }*/ - - private User loadGroups(User user) { - if (user == null) - return null; - user.setNextGroups(this.groupService.getAllGroupsOfUser(user)); - return user; - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java deleted file mode 100644 index dde34d1fef6..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.netgrif.application.engine.auth.service.interfaces; - -import com.netgrif.application.engine.auth.domain.Authority; - -import java.util.List; - -public interface IAuthorityService { - - List findAll(); - - Authority getOrCreate(String name); - - Authority getOrCreatePermission(String name); - - Authority getOrCreateRole(String name); - - List getAllPermissions(); - - List getAllRoles(); - - Authority getOne(String id); - - List findAllByIds(List ids); -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorizationService.java deleted file mode 100644 index 81feafc98d7..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorizationService.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.netgrif.application.engine.auth.service.interfaces; - -public interface IAuthorizationService { - boolean hasAuthority(String authority); -} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IRegistrationService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IRegistrationService.java deleted file mode 100644 index 4558765f277..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IRegistrationService.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.netgrif.application.engine.auth.service.interfaces; - -import com.netgrif.application.engine.auth.domain.RegisteredUser; -import com.netgrif.application.engine.auth.service.InvalidUserTokenException; -import com.netgrif.application.engine.auth.web.requestbodies.NewUserRequest; -import com.netgrif.application.engine.auth.web.requestbodies.RegistrationRequest; - -import java.time.LocalDateTime; - -public interface IRegistrationService { - - void removeExpiredUsers(); - - void resetExpiredToken(); - - void changePassword(RegisteredUser user, String newPassword); - - void encodeUserPassword(RegisteredUser user); - - boolean stringMatchesUserPassword(RegisteredUser user, String passwordToCompare); - - boolean verifyToken(String token); - - RegisteredUser createNewUser(NewUserRequest newUser); - - RegisteredUser registerUser(RegistrationRequest registrationRequest) throws InvalidUserTokenException; - - RegisteredUser resetPassword(String email); - - RegisteredUser recover(String email, String newPassword); - - String generateTokenKey(); - - String[] decodeToken(String token) throws InvalidUserTokenException; - - String encodeToken(String email, String tokenKey); - - LocalDateTime generateExpirationDate(); - - boolean isPasswordSufficient(String password); -} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java deleted file mode 100644 index 4d05f8e7f50..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.netgrif.application.engine.auth.service.interfaces; - -import com.netgrif.application.engine.auth.domain.AnonymousUser; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.web.requestbodies.UpdateUserRequest; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import org.bson.types.ObjectId; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.security.core.Authentication; - -import java.util.List; -import java.util.Set; - -public interface IUserService { - - IUser findByAuth(Authentication auth); - - IUser save(IUser user); - - IUser saveNewAndAuthenticate(IUser user); - - IUser saveNew(IUser user); - - AnonymousUser saveNewAnonymous(AnonymousUser user); - - IUser update(IUser user, UpdateUserRequest updates); - - IUser findById(String id); - - IUser resolveById(String id); - - IUser findByEmail(String email); - - IUser findAnonymousByEmail(String email); - - List findAll(); - - Page findAllCoMembers(LoggedUser loggedUser, Pageable pageable); - - List findAllByIds(Set ids); - - Page findAllActiveByProcessRoles(Set roleIds, Pageable pageable); - - void addDefaultRole(IUser user); - - List findAllByProcessRoles(Set roleIds); - - void addDefaultAuthorities(IUser user); - - IUser assignAuthority(String userId, String authorityId); - - IUser getLoggedOrSystem(); - - IUser getLoggedUser(); - - IUser getSystem(); - - LoggedUser getAnonymousLogged(); - - LoggedUser getLoggedUserFromContext(); - - IUser addRole(IUser user, String roleStringId); - - Page searchAllCoMembers(String query, LoggedUser principal, Pageable pageable); - - IUser removeRole(IUser user, String roleStringId); - - void removeRoleOfDeletedPetriNet(PetriNet net); - - void deleteUser(IUser user); - - Page searchAllCoMembers(String query, List roles, List negateRoleIds, LoggedUser principal, Pageable pageable); - - IUser createSystemUser(); - - boolean existsById(String id); - - IUser getUserFromLoggedUser(LoggedUser loggedUser); -} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/PublicUserController.java b/src/main/java/com/netgrif/application/engine/auth/web/PublicUserController.java deleted file mode 100644 index 58acd02fb58..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/web/PublicUserController.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.netgrif.application.engine.auth.web; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.auth.web.requestbodies.UserSearchRequestBody; -import com.netgrif.application.engine.auth.web.responsebodies.User; -import com.netgrif.application.engine.auth.web.responsebodies.UserResource; -import com.netgrif.application.engine.auth.web.responsebodies.UserResourceAssembler; -import com.netgrif.application.engine.settings.domain.Preferences; -import com.netgrif.application.engine.settings.service.IPreferencesService; -import com.netgrif.application.engine.settings.web.PreferencesResource; -import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; -import com.netgrif.application.engine.workflow.web.responsebodies.ResourceLinkAssembler; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.extern.slf4j.Slf4j; -import org.bson.types.ObjectId; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.web.PagedResourcesAssembler; -import org.springframework.hateoas.Link; -import org.springframework.hateoas.MediaTypes; -import org.springframework.hateoas.PagedModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.*; - -import javax.inject.Provider; -import java.util.Locale; -import java.util.stream.Collectors; - -@Slf4j -@RestController -@ConditionalOnProperty( - value = "nae.public.user.web.enabled", - havingValue = "true", - matchIfMissing = true -) -@Tag(name = "Public User Controller") -@RequestMapping("/api/public/user") -public class PublicUserController { - - @Autowired - private Provider userResourceAssemblerProvider; - - @Autowired - private IUserService userService; - - @Autowired - private IPreferencesService preferencesService; - - public PublicUserController() { - } - - protected UserResourceAssembler getUserResourceAssembler(String selfRel) { - UserResourceAssembler result = userResourceAssemblerProvider.get(); - result.initialize(selfRel); - return result; - } - - @Operation(summary = "Get logged user") - @GetMapping(value = "/me", produces = MediaTypes.HAL_JSON_VALUE) - public UserResource getLoggedUser() { - return new UserResource(new User(userService.getAnonymousLogged().transformToUser()), "profile"); - } - - @Operation(summary = "Generic user search") - @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public PagedModel search(@RequestBody UserSearchRequestBody query, Pageable pageable, PagedResourcesAssembler assembler, Locale locale) { - Page page = userService.searchAllCoMembers(query.getFulltext(), - query.getRoles().stream().map(ObjectId::new).collect(Collectors.toList()), - query.getNegativeRoles().stream().map(ObjectId::new).collect(Collectors.toList()), - userService.getAnonymousLogged(), pageable); - - Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(PublicUserController.class) - .search(query, pageable, assembler, locale)).withRel("search"); - PagedModel resources = assembler.toModel(page, getUserResourceAssembler("search"), selfLink); - ResourceLinkAssembler.addLinks(resources, IUser.class, selfLink.getRel().toString()); - return resources; - } - - @Operation(summary = "Get user's preferences") - @GetMapping(value = "/preferences", produces = MediaTypes.HAL_JSON_VALUE) - public PreferencesResource preferences() { - String userId = userService.getAnonymousLogged().transformToAnonymousUser().getStringId(); - Preferences preferences = preferencesService.get(userId); - - if (preferences == null) { - preferences = new Preferences(userId); - } - - return new PreferencesResource(preferences); - } - - @Operation(summary = "Set user's preferences") - @PostMapping(value = "/preferences", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public MessageResource savePreferences(@RequestBody Preferences preferences) { - try { - String userId = userService.getAnonymousLogged().transformToAnonymousUser().getStringId(); - preferences.setUserId(userId); - preferencesService.save(preferences); - return MessageResource.successMessage("User preferences saved"); - } catch (Exception e) { - log.error(e.getMessage(), e); - return MessageResource.errorMessage("Saving user preferences failed"); - } - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java deleted file mode 100644 index 6a60cd34223..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ /dev/null @@ -1,237 +0,0 @@ -package com.netgrif.application.engine.auth.web; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.domain.throwable.UnauthorisedRequestException; -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.auth.web.requestbodies.UpdateUserRequest; -import com.netgrif.application.engine.auth.web.requestbodies.UserSearchRequestBody; -import com.netgrif.application.engine.auth.web.responsebodies.AuthoritiesResources; -import com.netgrif.application.engine.auth.web.responsebodies.User; -import com.netgrif.application.engine.auth.web.responsebodies.UserResource; -import com.netgrif.application.engine.auth.web.responsebodies.UserResourceAssembler; -import com.netgrif.application.engine.configuration.properties.ServerAuthProperties; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; -import com.netgrif.application.engine.security.service.ISecurityContextService; -import com.netgrif.application.engine.settings.domain.Preferences; -import com.netgrif.application.engine.settings.service.IPreferencesService; -import com.netgrif.application.engine.settings.web.PreferencesResource; -import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; -import com.netgrif.application.engine.workflow.web.responsebodies.ResourceLinkAssembler; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.extern.slf4j.Slf4j; -import org.bson.types.ObjectId; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.web.PagedResourcesAssembler; -import org.springframework.hateoas.Link; -import org.springframework.hateoas.MediaTypes; -import org.springframework.hateoas.PagedModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; -import org.springframework.http.MediaType; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.Authentication; -import org.springframework.web.bind.annotation.*; - -import javax.inject.Provider; -import java.util.List; -import java.util.Locale; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -@Slf4j -@RestController -@RequestMapping("/api/user") -@ConditionalOnProperty( - value = "nae.user.web.enabled", - havingValue = "true", - matchIfMissing = true -) -@Tag(name = "User") -public class UserController { - - @Autowired - private IUserService userService; - - @Autowired - private IProcessRoleService processRoleService; - - @Autowired - private IAuthorityService authorityService; - - @Autowired - private IPreferencesService preferencesService; - - @Autowired - private ServerAuthProperties serverAuthProperties; - - @Autowired - private Provider userResourceAssemblerProvider; - - @Autowired - private ISecurityContextService securityContextService; - - protected UserResourceAssembler getUserResourceAssembler(String selfRel) { - UserResourceAssembler result = userResourceAssemblerProvider.get(); - result.initialize(selfRel); - return result; - } - - @Operation(summary = "Get all users", security = {@SecurityRequirement(name = "BasicAuth")}) - @GetMapping(produces = MediaTypes.HAL_JSON_VALUE) - public PagedModel getAll(Pageable pageable, PagedResourcesAssembler assembler, Authentication auth, Locale locale) { - Page page = userService.findAllCoMembers((LoggedUser) auth.getPrincipal(), pageable); - Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(UserController.class) - .getAll(pageable, assembler, auth, locale)).withRel("all"); - PagedModel resources = assembler.toModel(page, getUserResourceAssembler("all"), selfLink); - ResourceLinkAssembler.addLinks(resources, IUser.class, selfLink.getRel().toString()); - return resources; - } - - - @Operation(summary = "Generic user search", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public PagedModel search(@RequestBody UserSearchRequestBody query, Pageable pageable, PagedResourcesAssembler assembler, Authentication auth, Locale locale) { - List roles = query.getRoles() == null ? null : query.getRoles().stream().map(ObjectId::new).collect(Collectors.toList()); - List negativeRoles = query.getNegativeRoles() == null ? null : query.getNegativeRoles().stream().map(ObjectId::new).collect(Collectors.toList()); - Page page = userService.searchAllCoMembers(query.getFulltext(), - roles, - negativeRoles, - (LoggedUser) auth.getPrincipal(), pageable); - Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(UserController.class) - .search(query, pageable, assembler, auth, locale)).withRel("search"); - PagedModel resources = assembler.toModel(page, getUserResourceAssembler("search"), selfLink); - ResourceLinkAssembler.addLinks(resources, IUser.class, selfLink.getRel().toString()); - return resources; - } - - @Operation(summary = "Get user by id", security = {@SecurityRequirement(name = "BasicAuth")}) - @GetMapping(value = "/{id}", produces = MediaTypes.HAL_JSON_VALUE) - public UserResource getUser(@PathVariable("id") String userId, Locale locale) { - LoggedUser actualUser = userService.getLoggedUserFromContext(); - LoggedUser loggedUser = actualUser.getSelfOrImpersonated(); - if (!loggedUser.isAdmin() && !Objects.equals(loggedUser.getId(), userId)) { - log.info("User {} trying to get another user with ID {}", actualUser.getUsername(), userId); - throw new IllegalArgumentException("Could not find user with id [" + userId + "]"); - } - IUser user = userService.resolveById(userId); - return new UserResource(new User(user), "profile"); - } - - @Operation(summary = "Get logged user", security = {@SecurityRequirement(name = "BasicAuth")}) - @GetMapping(value = "/me", produces = MediaTypes.HAL_JSON_VALUE) - public UserResource getLoggedUser(Authentication auth, Locale locale) { - return new UserResource(new User(((LoggedUser)auth.getPrincipal()).transformToUser()), "me"); - } - - @Operation(summary = "Update user", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping(value = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public UserResource updateUser(@PathVariable("id") String userId, @RequestBody UpdateUserRequest updates, Authentication auth, Locale locale) throws UnauthorisedRequestException { - if (!serverAuthProperties.isEnableProfileEdit()) return null; - - LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); - IUser user = userService.resolveById(userId); - if (user == null || (!loggedUser.isAdmin() && !Objects.equals(loggedUser.getId(), userId))) - throw new UnauthorisedRequestException("User " + loggedUser.getUsername() + " doesn't have permission to modify profile of " + user.transformToLoggedUser().getUsername()); - - user = userService.update(user, updates); - securityContextService.saveToken(userId); - if (Objects.equals(loggedUser.getId(), userId)) { - loggedUser.setFullName(user.getFullName()); - securityContextService.reloadSecurityContext(loggedUser); - } - log.info("Updating user {} with data {}", user.getEmail(), updates.toString()); - return new UserResource(new User(user), "profile"); - } - - @Operation(summary = "Get all users with specified roles", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping(value = "/role", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public PagedModel getAllWithRole(@RequestBody Set roleIds, Pageable pageable, PagedResourcesAssembler assembler, Locale locale) { - Page page = userService.findAllActiveByProcessRoles(roleIds, pageable); - Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(UserController.class) - .getAllWithRole(roleIds, pageable, assembler, locale)).withRel("role"); - PagedModel resources = assembler.toModel(page, getUserResourceAssembler("role"), selfLink); - ResourceLinkAssembler.addLinks(resources, IUser.class, selfLink.getRel().toString()); - return resources; - } - - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") - @Operation(summary = "Assign role to the user", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping(value = "/{id}/role/assign", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK"), - @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), - }) - public MessageResource assignRolesToUser(@PathVariable("id") String userId, @RequestBody Set roleIds, Authentication auth) { - try { - processRoleService.assignRolesToUser(userId, roleIds, (LoggedUser) auth.getPrincipal()); - log.info("Process roles {} assigned to user {}", roleIds, userId); - return MessageResource.successMessage("Selected roles assigned to user " + userId); - } catch (IllegalArgumentException e) { - log.error(e.getMessage()); - return MessageResource.errorMessage("Assigning roles to user " + userId + " has failed!"); - } - } - - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") - @Operation(summary = "Get all authorities of the system", - description = "Caller must have the ADMIN role", - security = {@SecurityRequirement(name = "BasicAuth")}) - @GetMapping(value = "/authority", produces = MediaTypes.HAL_JSON_VALUE) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK"), - @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), - }) - public AuthoritiesResources getAllAuthorities(Authentication auth) { - return new AuthoritiesResources(authorityService.findAll()); - } - - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") - @Operation(summary = "Assign authority to the user", - description = "Caller must have the ADMIN role", - security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping(value = "/{id}/authority/assign", consumes = MediaType.TEXT_PLAIN_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK"), - @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), - }) - public MessageResource assignAuthorityToUser(@PathVariable("id") String userId, @RequestBody String authorityId) { - userService.assignAuthority(userId, authorityId); - return MessageResource.successMessage("Authority " + authorityId + " assigned to user " + userId); - } - - @Operation(summary = "Get user's preferences", security = {@SecurityRequirement(name = "BasicAuth")}) - @GetMapping(value = "/preferences", produces = MediaTypes.HAL_JSON_VALUE) - public PreferencesResource preferences(Authentication auth) { - String userId = ((LoggedUser) auth.getPrincipal()).getId(); - Preferences preferences = preferencesService.get(userId); - - if (preferences == null) { - preferences = new Preferences(userId); - } - - return new PreferencesResource(preferences); - } - - @Operation(summary = "Set user's preferences", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping(value = "/preferences", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public MessageResource savePreferences(@RequestBody Preferences preferences, Authentication auth) { - try { - String userId = ((LoggedUser) auth.getPrincipal()).getId(); - preferences.setUserId(userId); - preferencesService.save(preferences); - return MessageResource.successMessage("User preferences saved"); - } catch (Exception e) { - log.error(e.getMessage(), e); - return MessageResource.errorMessage("Saving user preferences failed"); - } - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewUserRequest.java b/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewUserRequest.java deleted file mode 100644 index 31692e5f206..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewUserRequest.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.netgrif.application.engine.auth.web.requestbodies; - -import lombok.Data; - -import java.util.Set; - -@Data -public class NewUserRequest { - - public String email; - public Set groups; - public Set processRoles; - - public NewUserRequest() { - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/UpdateUserRequest.java b/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/UpdateUserRequest.java deleted file mode 100644 index b12142299ac..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/UpdateUserRequest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.netgrif.application.engine.auth.web.requestbodies; - -public class UpdateUserRequest { - - public String telNumber; - public String avatar; - public String name; - public String surname; - - public UpdateUserRequest() { - } - - @Override - public String toString() { - return "UpdateUserRequest{" + - "telNumber='" + telNumber + '\'' + - ", avatar='" + avatar + '\'' + - ", name='" + name + '\'' + - ", surname='" + surname + '\'' + - '}'; - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/UserSearchRequestBody.java b/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/UserSearchRequestBody.java deleted file mode 100644 index 1716dfdac2a..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/UserSearchRequestBody.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.netgrif.application.engine.auth.web.requestbodies; - -import lombok.Data; - -import java.util.List; - -@Data -public class UserSearchRequestBody { - - private String fulltext; - - private List roles; - - private List negativeRoles; -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthoritiesResources.java b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthoritiesResources.java deleted file mode 100644 index 12aeeb5b95a..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthoritiesResources.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.netgrif.application.engine.auth.web.responsebodies; - - -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.web.UserController; -import org.springframework.hateoas.CollectionModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; - -public class AuthoritiesResources extends CollectionModel { - public AuthoritiesResources(Iterable content) { - super(content); - buildLinks(); - } - - public AuthoritiesResources() { - } - - public void buildLinks() { - add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(UserController.class) - .getAllAuthorities(null)).withSelfRel()); - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/IProcessRoleFactory.java b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/IProcessRoleFactory.java deleted file mode 100644 index 8550718180f..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/IProcessRoleFactory.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.netgrif.application.engine.auth.web.responsebodies; - -import java.util.Locale; - -public interface IProcessRoleFactory { - ProcessRole getProcessRole(com.netgrif.application.engine.petrinet.domain.roles.ProcessRole role, Locale locale); -} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/ProcessRole.java b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/ProcessRole.java deleted file mode 100644 index a2b46d5129c..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/ProcessRole.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.netgrif.application.engine.auth.web.responsebodies; - -import lombok.Data; - -import java.util.Locale; - -@Data -public class ProcessRole { - - private String stringId; - - private String name; - - private String description; - - private String importId; - - // net attributes are set in the Factory service - private String netImportId; - - private String netVersion; - - private String netStringId; - - /** - * The constructor doesn't set attributes regarding the Petri net. - * - * Use the ProcessRoleFactory to create instances that have these attributes set. - */ - public ProcessRole(com.netgrif.application.engine.petrinet.domain.roles.ProcessRole role, Locale locale) { - stringId = role.getStringId(); - name = role.getLocalisedName(locale); - description = role.getDescription(); - importId = role.getImportId(); - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/ProcessRoleFactory.java b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/ProcessRoleFactory.java deleted file mode 100644 index 95f6b1ad19d..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/ProcessRoleFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.netgrif.application.engine.auth.web.responsebodies; - -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import org.bson.types.ObjectId; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.Locale; - -@Service -public class ProcessRoleFactory implements IProcessRoleFactory { - - @Autowired - private IPetriNetService petriNetService; - - @Override - public ProcessRole getProcessRole(com.netgrif.application.engine.petrinet.domain.roles.ProcessRole role, Locale locale) { - /*if (!role.getStringId().equals(userProcessRole.getRoleId())) { - throw new IllegalArgumentException(String.format("ProcessRole StringId (%s) and UserProcessRole roleId (%s) must match!", role.getStringId(), userProcessRole.getRoleId())); - }*/ - ProcessRole result = new ProcessRole(role, locale); - PetriNet net = petriNetService.get(new ObjectId(role.getNetId())); - result.setNetStringId(net.getStringId()); - result.setNetImportId(net.getImportId()); - result.setNetVersion(net.getVersion().toString()); - return result; - } - -} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java deleted file mode 100644 index acd7e129ac6..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.netgrif.application.engine.auth.web.responsebodies; - -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.IUser; -import lombok.Data; - -import java.util.Set; - -@Data -public class User { - - private String id; - - private String email; - - private String telNumber; - - private String avatar; - - private String name; - - private String surname; - - private String fullName; - - private Set authorities; - - // process roles are set with the factory - private Set processRoles; - - private Set nextGroups; - - private User impersonated; - - public User(IUser user) { - id = user.getStringId(); - email = user.getEmail(); - avatar = user.getAvatar(); - name = user.getName(); - surname = user.getSurname(); - fullName = user.getFullName(); - } - - /** - * This static method doesn't set attributes regarding the ProcessRoles - * - * Use the IUserFactory service to create instances that have these attributes set. - */ - public static User createSmallUser(IUser user) { - return new User(user); - } - - /** - * This static method doesn't set attributes regarding the ProcessRoles - * - * Use the IUserFactory service to create instances that have these attributes set. - */ - public static User createUser(IUser user) { - User result = new User(user); - result.setTelNumber(user.getTelNumber()); - result.setAuthorities(user.getAuthorities()); - result.setNextGroups(user.getNextGroups()); - return result; - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/UserResource.java b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/UserResource.java deleted file mode 100644 index bee4235ac8f..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/UserResource.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.netgrif.application.engine.auth.web.responsebodies; - - -import com.netgrif.application.engine.auth.web.UserController; -import org.springframework.hateoas.EntityModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; - -import java.util.ArrayList; - -// TODO: release/8.0.0 remove User, replace with IUser -public class UserResource extends EntityModel { - - public UserResource(User content, String selfRel) { - super(content, new ArrayList<>()); - buildLinks(selfRel); - } - - private void buildLinks(String selfRel) { - WebMvcLinkBuilder getLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(UserController.class) - .getUser(getContent().getId(), null)); - add(selfRel.equalsIgnoreCase("profile") ? getLink.withSelfRel() : getLink.withRel("profile")); - - WebMvcLinkBuilder roleLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(UserController.class) - .assignRolesToUser(getContent().getId(), null, null)); - add(selfRel.equalsIgnoreCase("assignProcessRole") ? roleLink.withSelfRel() : roleLink.withRel("assignProcessRole")); - - WebMvcLinkBuilder authorityLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(UserController.class) - .assignAuthorityToUser(getContent().getId(), null)); - add(selfRel.equalsIgnoreCase("assignRole") ? authorityLink.withSelfRel() : authorityLink.withRel("assignRole")); - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/UserResourceAssembler.java b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/UserResourceAssembler.java deleted file mode 100644 index 3d221a2afa2..00000000000 --- a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/UserResourceAssembler.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.netgrif.application.engine.auth.web.responsebodies; - -import com.netgrif.application.engine.auth.domain.IUser; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.hateoas.server.RepresentationModelAssembler; - -import java.util.Locale; - -public class UserResourceAssembler implements RepresentationModelAssembler { - - private String selfRel; - - private boolean initialized = false; - - public UserResourceAssembler() { - } - - public void initialize(String selfRel) { - this.selfRel = selfRel; - this.initialized = true; - } - - @Override - public UserResource toModel(IUser entity) { - if (!initialized) { - throw new IllegalStateException("You must initialize the UserResourceAssembler before calling the toResource method! To initialize the assembler call the initialize method."); - } - - return new UserResource(new User(entity), selfRel); - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/authentication/domain/Identity.java b/src/main/java/com/netgrif/application/engine/authentication/domain/Identity.java new file mode 100644 index 00000000000..c3f6f6d0730 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/domain/Identity.java @@ -0,0 +1,136 @@ +package com.netgrif.application.engine.authentication.domain; + +import com.netgrif.application.engine.authentication.domain.constants.IdentityConstants; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.SystemCase; + +import java.time.LocalDateTime; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class Identity extends SystemCase { + + public Identity(Case identityCase) { + super(identityCase); + } + + @Override + protected CanInitializeOutcome canInitialize(Case identityCase) { + return new CanInitializeOutcome("Provided identity case is of different process", + identityCase.getProcessIdentifier().equals(IdentityConstants.PROCESS_IDENTIFIER)); + } + + /** + * todo javadoc + * */ + public boolean isActive() { + String state = (String) getCase().getDataSet().get(IdentityConstants.STATE_FIELD_ID).getRawValue(); + return state.equalsIgnoreCase(IdentityState.ACTIVE.name()); + } + + /** + * todo javadoc + * */ + public String getFirstname() { + return (String) getCase().getDataSet().get(IdentityConstants.FIRSTNAME_FIELD_ID).getRawValue(); + } + + /** + * todo javadoc + * */ + public String getLastname() { + return (String) getCase().getDataSet().get(IdentityConstants.LASTNAME_FIELD_ID).getRawValue(); + } + + /** + * todo javadoc + * */ + public String getFullName() { + return String.join(" ", getFirstname(), getLastname()); + } + + /** + * todo javadoc + * */ + public String getMainActorId() { + List mainActorIdAsList = ((CaseField) getCase().getDataSet().get(IdentityConstants.MAIN_ACTOR_FIELD_ID)).getRawValue(); + if (mainActorIdAsList != null && !mainActorIdAsList.isEmpty()) { + return mainActorIdAsList.get(0); + } + return null; + } + + /** + * todo javadoc + * */ + public List getAdditionalActorIds() { + return ((CaseField) getCase().getDataSet().get(IdentityConstants.ADDITIONAL_ACTORS_FIELD_ID)).getRawValue(); + } + + /** + * todo javadoc + * */ + public Set getAllActors() { + List additionalActorIds = getAdditionalActorIds(); + Set allActorIds; + if (additionalActorIds == null) { + allActorIds = new HashSet<>(); + } else { + allActorIds = new HashSet<>(getAdditionalActorIds()); + } + + String mainActorId = getMainActorId(); + if (mainActorId == null) { + return allActorIds; + } + + allActorIds.add(mainActorId); + return allActorIds; + } + + /** + * todo javadoc + * */ + public String getRegistrationToken() { + return (String) getCase().getDataSet().get(IdentityConstants.REGISTRATION_TOKEN_FIELD_ID).getRawValue(); + } + + /** + * todo javadoc + * */ + public LocalDateTime getExpirationDate() { + return (LocalDateTime) getCase().getDataSet().get(IdentityConstants.EXPIRATION_DATE_FIELD_ID).getRawValue(); + } + + /** + * todo javadoc + * */ + public String getUsername() { + return (String) getCase().getDataSet().get(IdentityConstants.USERNAME_FIELD_ID).getRawValue(); + } + + /** + * todo javadoc + * */ + public String getPassword() { + return (String) getCase().getDataSet().get(IdentityConstants.PASSWORD_FIELD_ID).getRawValue(); + } + + /** + * todo javadoc + * */ + public LoggedIdentity toSession() { + String username = (String) getCase().getDataSet().get(IdentityConstants.USERNAME_FIELD_ID).getRawValue(); + + return LoggedIdentity.with() + .username(username) + .password(this.getPassword()) + .fullName(this.getFullName()) + .identityId(this.getStringId()) + .activeActorId(this.getMainActorId()) + .properties(this.getProperties()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/authentication/domain/IdentityProperties.java b/src/main/java/com/netgrif/application/engine/authentication/domain/IdentityProperties.java new file mode 100644 index 00000000000..8c715321de0 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/domain/IdentityProperties.java @@ -0,0 +1,5 @@ +package com.netgrif.application.engine.authentication.domain; + +public class IdentityProperties { + public static final String ANONYMOUS_AUTH_KEY = "anonymousIdentity"; +} diff --git a/src/main/java/com/netgrif/application/engine/authentication/domain/IdentityState.java b/src/main/java/com/netgrif/application/engine/authentication/domain/IdentityState.java new file mode 100644 index 00000000000..af7041827de --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/domain/IdentityState.java @@ -0,0 +1,7 @@ +package com.netgrif.application.engine.authentication.domain; + +public enum IdentityState { + ACTIVE, + BLOCKED, + INVITED +} diff --git a/src/main/java/com/netgrif/application/engine/authentication/domain/LoggedIdentity.java b/src/main/java/com/netgrif/application/engine/authentication/domain/LoggedIdentity.java new file mode 100644 index 00000000000..cea3dd18c77 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/domain/LoggedIdentity.java @@ -0,0 +1,33 @@ +package com.netgrif.application.engine.authentication.domain; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.springframework.security.core.userdetails.User; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +/** + * todo javadoc + * */ +@Getter +public class LoggedIdentity extends User { + protected final String fullName; + protected final String identityId; + protected final Map properties; + + @Setter + protected String activeActorId; + + @Builder(builderMethodName = "with") + public LoggedIdentity(String fullName, String identityId, String activeActorId, String username, String password, + Map properties) { + super(username, password, new HashSet<>()); + this.fullName = fullName; + this.identityId = identityId; + this.activeActorId = activeActorId; + this.properties = properties == null ? new HashMap<>() : properties; + } +} diff --git a/src/main/java/com/netgrif/application/engine/authentication/domain/PublicStrategy.java b/src/main/java/com/netgrif/application/engine/authentication/domain/PublicStrategy.java new file mode 100644 index 00000000000..22516960505 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/domain/PublicStrategy.java @@ -0,0 +1,27 @@ +package com.netgrif.application.engine.authentication.domain; + +import com.netgrif.application.engine.configuration.security.factory.AdvancedPublicAuthenticationFilterFactory; +import com.netgrif.application.engine.configuration.security.factory.BasicPublicAuthenticationFilterFactory; +import com.netgrif.application.engine.configuration.security.factory.SimplePublicAuthenticationFilterFactory; + +/** + * todo javadoc + * identity vs actor + * warning for changing strategy in running system + */ +public enum PublicStrategy { + /** todo javadoc */ + SIMPLE(SimplePublicAuthenticationFilterFactory.class), + + /** todo javadoc */ + BASIC(BasicPublicAuthenticationFilterFactory.class), + + /** todo javadoc */ + ADVANCED(AdvancedPublicAuthenticationFilterFactory.class); + + public final Class factoryClass; + + PublicStrategy(Class factoryClass) { + this.factoryClass = factoryClass; + } +} diff --git a/src/main/java/com/netgrif/application/engine/authentication/domain/constants/AnonymIdentityConstants.java b/src/main/java/com/netgrif/application/engine/authentication/domain/constants/AnonymIdentityConstants.java new file mode 100644 index 00000000000..d69822d23a8 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/domain/constants/AnonymIdentityConstants.java @@ -0,0 +1,22 @@ +package com.netgrif.application.engine.authentication.domain.constants; + +public class AnonymIdentityConstants { + public static final String DEFAULT_USERNAME_PREFIX = "anonymous"; + public static final String USERNAME_TEMPLATE = "%s@netgrif.com"; + public static final String FIRSTNAME = "Anonymous"; + public static final String LASTNAME = "Identity"; + + /** + * todo javadoc + */ + public static String usernameOf(String usernamePrefix) { + return String.format(USERNAME_TEMPLATE, usernamePrefix); + } + + /** + * todo javadoc + */ + public static String defaultUsername() { + return usernameOf(DEFAULT_USERNAME_PREFIX); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authentication/domain/constants/IdentityConstants.java b/src/main/java/com/netgrif/application/engine/authentication/domain/constants/IdentityConstants.java new file mode 100644 index 00000000000..c456601ed58 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/domain/constants/IdentityConstants.java @@ -0,0 +1,15 @@ +package com.netgrif.application.engine.authentication.domain.constants; + +public class IdentityConstants { + public static final String PROCESS_IDENTIFIER = "identity"; + public static final String FILE_PATH = "engine-processes/identity.xml"; + public static final String USERNAME_FIELD_ID = "username"; + public static final String FIRSTNAME_FIELD_ID = "firstname"; + public static final String LASTNAME_FIELD_ID = "lastname"; + public static final String PASSWORD_FIELD_ID = "password"; + public static final String STATE_FIELD_ID = "state"; + public static final String EXPIRATION_DATE_FIELD_ID = "expiration_date"; + public static final String REGISTRATION_TOKEN_FIELD_ID = "registration_token"; + public static final String MAIN_ACTOR_FIELD_ID = "main_actor_id"; + public static final String ADDITIONAL_ACTORS_FIELD_ID = "additional_actor_ids"; +} diff --git a/src/main/java/com/netgrif/application/engine/authentication/domain/constants/SystemUserConstants.java b/src/main/java/com/netgrif/application/engine/authentication/domain/constants/SystemUserConstants.java new file mode 100644 index 00000000000..f16b68568a3 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/domain/constants/SystemUserConstants.java @@ -0,0 +1,7 @@ +package com.netgrif.application.engine.authentication.domain.constants; + +public class SystemUserConstants { + public static final String EMAIL = "engine@netgrif.com"; + public static final String FIRSTNAME = "Application"; + public static final String LASTNAME = "Engine"; +} diff --git a/src/main/java/com/netgrif/application/engine/authentication/domain/params/IdentityParams.java b/src/main/java/com/netgrif/application/engine/authentication/domain/params/IdentityParams.java new file mode 100644 index 00000000000..378c447f60e --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/domain/params/IdentityParams.java @@ -0,0 +1,106 @@ +package com.netgrif.application.engine.authentication.domain.params; + +import com.netgrif.application.engine.authentication.domain.IdentityState; +import com.netgrif.application.engine.authentication.domain.constants.IdentityConstants; +import com.netgrif.application.engine.petrinet.domain.dataset.*; +import com.netgrif.application.engine.workflow.domain.CaseParams; +import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Map; + +@Data +@EqualsAndHashCode(callSuper = true) +public class IdentityParams extends CaseParams { + protected TextField username; + protected TextField firstname; + protected TextField lastname; + protected TextField password; + protected EnumerationMapField state; + protected DateTimeField expirationDateTime; + protected TextField registrationToken; + protected CaseField mainActor; + protected CaseField additionalActors; + + @Builder(builderMethodName = "with") + public IdentityParams(Map properties, TextField username, TextField firstname, TextField lastname, + TextField password, EnumerationMapField state, DateTimeField expirationDateTime, + TextField registrationToken, CaseField mainActor, CaseField additionalActors) { + super(properties); + this.username = username; + this.firstname = firstname; + this.lastname = lastname; + this.password = password; + this.state = state; + this.expirationDateTime = expirationDateTime; + this.registrationToken = registrationToken; + this.mainActor = mainActor; + this.additionalActors = additionalActors; + } + + @Override + public DataSet toDataSet() { + DataSet dataSet = new DataSet(); + + dataSet.put(IdentityConstants.USERNAME_FIELD_ID, this.username); + dataSet.put(IdentityConstants.FIRSTNAME_FIELD_ID, this.firstname); + dataSet.put(IdentityConstants.LASTNAME_FIELD_ID, this.lastname); + dataSet.put(IdentityConstants.PASSWORD_FIELD_ID, this.password); + if (this.canForceActiveState()) { + dataSet.put(IdentityConstants.STATE_FIELD_ID, new TextField(IdentityState.ACTIVE.name().toLowerCase())); + } else { + if (this.state != null && this.state.getRawValue() != null) { + this.state.setRawValue(this.state.getRawValue().toLowerCase()); + } + dataSet.put(IdentityConstants.STATE_FIELD_ID, this.state); + } + dataSet.put(IdentityConstants.EXPIRATION_DATE_FIELD_ID, this.expirationDateTime); + dataSet.put(IdentityConstants.REGISTRATION_TOKEN_FIELD_ID, this.registrationToken); + dataSet.put(IdentityConstants.MAIN_ACTOR_FIELD_ID, this.mainActor); + dataSet.put(IdentityConstants.ADDITIONAL_ACTORS_FIELD_ID, this.additionalActors); + + return dataSet; + } + + @Override + public String targetProcessIdentifier() { + return IdentityConstants.PROCESS_IDENTIFIER; + } + + /** + * todo javadoc + * */ + public String getFullName() { + if (this.firstname == null || this.lastname == null) { + return ""; + } + return String.join(" ", this.firstname.getRawValue(), this.lastname.getRawValue()); + } + + /** + * todo javadoc + * */ + public String getPassword() { + if (this.password == null) { + return null; + } + return this.password.getRawValue(); + } + + /** + * todo javadoc + * */ + protected boolean canForceActiveState() { + return !hasFieldAnyValue(this.state) + && hasFieldAnyValue(this.username) && hasFieldAnyValue(this.password) && hasFieldAnyValue(this.mainActor); + } + + /** + * todo javadoc + * */ + protected boolean hasFieldAnyValue(Field field) { + return field != null && field.getRawValue() != null; + } +} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/throwable/UnauthorisedRequestException.java b/src/main/java/com/netgrif/application/engine/authentication/domain/throwable/UnauthorisedRequestException.java similarity index 81% rename from src/main/java/com/netgrif/application/engine/auth/domain/throwable/UnauthorisedRequestException.java rename to src/main/java/com/netgrif/application/engine/authentication/domain/throwable/UnauthorisedRequestException.java index 82ea5767d06..1b6f651ea44 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/throwable/UnauthorisedRequestException.java +++ b/src/main/java/com/netgrif/application/engine/authentication/domain/throwable/UnauthorisedRequestException.java @@ -1,4 +1,4 @@ -package com.netgrif.application.engine.auth.domain.throwable; +package com.netgrif.application.engine.authentication.domain.throwable; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/src/main/java/com/netgrif/application/engine/authentication/domain/throwable/WrongPublicConfigurationException.java b/src/main/java/com/netgrif/application/engine/authentication/domain/throwable/WrongPublicConfigurationException.java new file mode 100644 index 00000000000..790dc1c2846 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/domain/throwable/WrongPublicConfigurationException.java @@ -0,0 +1,12 @@ +package com.netgrif.application.engine.authentication.domain.throwable; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.FORBIDDEN) +public class WrongPublicConfigurationException extends Exception { + + public WrongPublicConfigurationException(String message) { + super(message); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authentication/service/IdentityService.java b/src/main/java/com/netgrif/application/engine/authentication/service/IdentityService.java new file mode 100644 index 00000000000..173e4070560 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/service/IdentityService.java @@ -0,0 +1,365 @@ +package com.netgrif.application.engine.authentication.service; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.IdentityState; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authentication.domain.constants.IdentityConstants; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.domain.User; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseSearchService; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.security.service.SecurityContextService; +import com.netgrif.application.engine.transaction.NaeTransaction; +import com.netgrif.application.engine.workflow.domain.CaseParams; +import com.netgrif.application.engine.workflow.domain.params.DeleteCaseParams; +import com.netgrif.application.engine.workflow.service.CrudSystemCaseService; +import com.netgrif.application.engine.workflow.service.SystemCaseFactoryRegistry; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import groovy.lang.Closure; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; +import org.springframework.data.mongodb.MongoTransactionManager; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +@Slf4j +@Service +public class IdentityService extends CrudSystemCaseService implements IIdentityService { + + // todo: release/8.0.0 make encoder configurable + private final BCryptPasswordEncoder passwordEncoder; + private final SecurityContextService securityContextService; + private final IUserService userService; + + public IdentityService(BCryptPasswordEncoder passwordEncoder, SecurityContextService securityContextService, + @Lazy IDataService dataService, @Lazy IWorkflowService workflowService, + @Lazy IElasticCaseSearchService elasticCaseSearchService, @Lazy IUserService userService, + SystemCaseFactoryRegistry systemCaseFactoryRegistry, @Lazy ISessionManagerService sessionManagerService, + MongoTransactionManager mongoTransactionManager) { + super(sessionManagerService, dataService, workflowService, systemCaseFactoryRegistry, elasticCaseSearchService, + mongoTransactionManager); + this.passwordEncoder = passwordEncoder; + this.securityContextService = securityContextService; + this.userService = userService; + } + + /** + * Returns the currently logged identity from the session manager. + * + * @return Currently logged identity. Can be null if no identity is logged in. + */ + @Override + public LoggedIdentity getLoggedIdentity() { + return sessionManagerService.getLoggedIdentity(); + } + + /** + * Finds identity by username data field. + * + * @param username username of the identity. If provided null, empty optional is returned + * + * @return If the identity exists, it's returned. If not, an empty optional is returned + * */ + @Override + public Optional findByUsername(String username) { + if (username == null) { + return Optional.empty(); + } + return findOneByQuery(fulltextFieldQuery(IdentityConstants.USERNAME_FIELD_ID, username)); + } + + /** + * Finds identity by provided {@link LoggedIdentity} + * + * @param loggedIdentity logged identity used to find the identity. If provided null, empty optional is returned + * + * @return If the identity exists, it's returned. If not, an empty optional is returned + * */ + @Override + public Optional findByLoggedIdentity(LoggedIdentity loggedIdentity) { + if (loggedIdentity == null) { + return Optional.empty(); + } + + Optional identityOpt = findById(loggedIdentity.getIdentityId()); + if (identityOpt.isEmpty()) { + log.warn("Logged identity [{}] has no identity in database!", loggedIdentity.getUsername()); + } + return identityOpt; + } + + /** + * Checks if the identity exists by username data field + * + * @param username username of the identity. If provided null, empty optional is returned + * + * @return True if the identity exists, else false. + * */ + @Override + public boolean existsByUsername(String username) { + if (username == null) { + return false; + } + return countByQuery(fulltextFieldQuery(IdentityConstants.USERNAME_FIELD_ID, username)) > 0; + } + + /** + * Finds all actor ids of the identity + * + * @param id The id of the identity. If provided null, empty set is returned + * + * @return Set of actor ids of the identity. Otherwise, an empty set is returned + * */ + @Override + public Set findActorIds(String id) { + Optional identityOpt = findById(id); + + if (identityOpt.isPresent()) { + return identityOpt.get().getAllActors(); + } + + return Set.of(); + } + + /** + * Find all identities with matched state, that are expired. + * + * @param state state of the identity. If provided null, empty list is returned + * @param dateTime expiration date time threshold. The identity is considered expired if the expiration date is + * before this value. If provided null, empty list is returned + * + * @return List of all identities, that match the requirements. Otherwise, an empty list is returned. + * */ + @Override + public List findAllByStateAndExpirationDateBefore(IdentityState state, LocalDateTime dateTime) { + if (state == null || dateTime == null) { + return List.of(); + } + return findAllByQuery(stateAndExpirationDateBeforeQuery(state, dateTime)).stream() + .map(Identity::new) + .collect(Collectors.toList()); + } + + /** + * Creates identity based on params. Password is encoded. User is created from the identity parameters. + * + * @param identityParams Parameters, that are used to create the identity. At least username must be provided. + * + * @return Created identity with the User (as {@link Identity#getMainActorId()}). Cannot be null. + * */ + @Override + public Identity createWithDefaultUser(IdentityParams identityParams) { + validateAndFixCreateParams(identityParams); + + UserParams userParams = UserParams.fromIdentityParams(identityParams); + if (!TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure(null) { + @Override + public Identity call() { + User defaultUser = userService.create(userParams); + identityParams.setMainActor(CaseField.withValue(List.of(defaultUser.getStringId()))); + return encodePasswordAndCreate(identityParams); + } + }) + .build(); + transaction.begin(); + return (Identity) transaction.getResultOfEvent(); + } else { + User defaultUser = userService.create(userParams); + identityParams.setMainActor(CaseField.withValue(List.of(defaultUser.getStringId()))); + return encodePasswordAndCreate(identityParams); + } + } + + /** + * Creates new identity with encoded password from provided parameters. + * + * @param params Parameters for creating identity. Password will be encoded before creation. + * @return Created identity with encoded password + * @throws IllegalArgumentException if parameters validation fails + * */ + @Override + public Identity encodePasswordAndCreate(IdentityParams params) { + encodePassword(params); + return create(params); + } + + /** + * Updates existing identity with provided parameters and encodes new password. + * + * @param identity Identity to be updated + * @param params Parameters containing updates. Password will be encoded before update. + * @return Updated identity with newly encoded password + * @throws IllegalArgumentException if identity or parameters validation fails + * */ + @Override + public Identity encodePasswordAndUpdate(Identity identity, IdentityParams params) { + encodePassword(params); + return update(identity, params); + } + + /** + * Adds a single additional actor to the identity. + * + * @param identity Identity to which the actor will be added + * @param actorId ID of the actor to be added as additional actor + * @return Updated identity with new additional actor + * @throws IllegalArgumentException if identity or actorId is null + * */ + @Override + public Identity addAdditionalActor(Identity identity, String actorId) { + if (identity == null) { + throw new IllegalArgumentException("Provided identity is null"); + } + if (actorId == null) { + throw new IllegalArgumentException("Provided actorId is null"); + } + + return addAdditionalActors(identity, Set.of(actorId)); + } + + /** + * Adds multiple additional actors to the identity. + * + * @param identity Identity to which the actors will be added + * @param actorIds Set of actor IDs to be added as additional actors + * @return Updated identity with new additional actors + * @throws IllegalArgumentException if identity is null or actorIds is null or empty + * */ + @Override + public Identity addAdditionalActors(Identity identity, Set actorIds) { + if (identity == null) { + throw new IllegalArgumentException("Provided identity is null"); + } + if (actorIds == null || actorIds.isEmpty()) { + throw new IllegalArgumentException("Additional actors are not provided"); + } + + List additionalActorIds; + if (identity.getAdditionalActorIds() != null) { + additionalActorIds = new ArrayList<>(identity.getAdditionalActorIds()); + additionalActorIds.addAll(actorIds); + } else { + additionalActorIds = new ArrayList<>(actorIds); + } + + return update(identity, IdentityParams.with() + .additionalActors(CaseField.withValue(additionalActorIds)) + .build()); + } + + /** + * Removes all identities in given state that expired before specified date. + * + * @param state State of identities to be removed + * @param dateTime Date threshold - identities expired before this date will be removed + * @return List of all removed identities + * @throws IllegalArgumentException if state or dateTime is null + * */ + @Override + public List removeAllByStateAndExpirationDateBefore(IdentityState state, LocalDateTime dateTime) { + if (state == null || dateTime == null) { + throw new IllegalArgumentException("Identity state or expiration date is null"); + } + + List identities = findAllByStateAndExpirationDateBefore(state, dateTime); + + if (!TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<>(null) { + @Override + public List call() { + for (Identity identity : identities) { + workflowService.deleteCase(new DeleteCaseParams(identity.getCase())); + } + return identities; + } + }) + .build(); + transaction.begin(); + } else { + for (Identity identity : identities) { + workflowService.deleteCase(new DeleteCaseParams(identity.getCase())); + } + } + + return identities; + } + + @Override + protected String getProcessIdentifier() { + return IdentityConstants.PROCESS_IDENTIFIER; + } + + @Override + protected String isUniqueQuery(CaseParams params) { + IdentityParams typedParams = (IdentityParams) params; + return fulltextFieldQuery(IdentityConstants.USERNAME_FIELD_ID, typedParams.getUsername().getRawValue()); + } + + @Override + protected void validateAndFixCreateParams(CaseParams params) throws IllegalArgumentException { + IdentityParams typedParams = (IdentityParams) params; + if (isTextFieldOrValueEmpty(typedParams.getUsername())) { + throw new IllegalArgumentException("Identity must have an username!"); + } + if (isForbidden(typedParams.getUsername().getRawValue())) { + throw new IllegalArgumentException(String.format("Identity username [%s] is reserved by the system.", + typedParams.getUsername().getRawValue())); + } + } + + @Override + protected void validateAndFixUpdateParams(CaseParams params) throws IllegalArgumentException { + IdentityParams typedParams = (IdentityParams) params; + if (typedParams.getUsername() == null) { + return; + } + if (isTextFieldValueEmpty(typedParams.getUsername())) { + throw new IllegalArgumentException("Identity must have an username!"); + } + if (isForbidden(typedParams.getUsername().getRawValue())) { + throw new IllegalArgumentException(String.format("Identity username [%s] is reserved by the system.", + typedParams.getUsername().getRawValue())); + } + } + + @Override + protected void postUpdateActions(Identity identity) { + if (securityContextService.isIdentityLogged(identity.getStringId())) { + securityContextService.reloadSecurityContext(identity.toSession()); + } + } + + private void encodePassword(IdentityParams params) { + String password = params.getPassword(); + if (password == null) { + params.setPassword(new TextField(null)); + return; + } + params.setPassword(new TextField(passwordEncoder.encode(password))); + } + + private static String stateAndExpirationDateBeforeQuery(IdentityState state, LocalDateTime dateTime) { + long timestamp = Timestamp.valueOf(dateTime).getTime(); + return String.format("dataSet.%s.keyValue:\"%s\" AND dataSet.%s.timestampValue:<=%d", + IdentityConstants.STATE_FIELD_ID, state.name().toLowerCase(), IdentityConstants.EXPIRATION_DATE_FIELD_ID, + timestamp); + } + +} diff --git a/src/main/java/com/netgrif/application/engine/authentication/service/InvalidIdentityTokenException.java b/src/main/java/com/netgrif/application/engine/authentication/service/InvalidIdentityTokenException.java new file mode 100644 index 00000000000..5519664851b --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/service/InvalidIdentityTokenException.java @@ -0,0 +1,8 @@ +package com.netgrif.application.engine.authentication.service; + +public class InvalidIdentityTokenException extends Exception { + + public InvalidIdentityTokenException(String token) { + super(String.format("Token %s has invalid format", token)); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authentication/service/LdapUserDetailsService.java b/src/main/java/com/netgrif/application/engine/authentication/service/LdapUserDetailsService.java new file mode 100644 index 00000000000..a04ce667b40 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/service/LdapUserDetailsService.java @@ -0,0 +1,33 @@ +package com.netgrif.application.engine.authentication.service; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.service.interfaces.ILoginAttemptService; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +import javax.servlet.http.HttpServletRequest; + +@ConditionalOnExpression("${nae.ldap.enabled:false}") +public class LdapUserDetailsService /*extends UserDetailsServiceImpl*/ { + + public LdapUserDetailsService(ApplicationEventPublisher publisher, ILoginAttemptService loginAttemptService, + HttpServletRequest request) { +// super(publisher, loginAttemptService, request); + } + +// @Override + protected Identity getLoggedUser(String email) throws UsernameNotFoundException { + return null; +// IUser user = userRepository.findByEmail(email); +// if (user == null) { +// throw new UsernameNotFoundException("No user was found for login: " + email); +// } else if (user.getState() != IdentityState.ACTIVE) { +// throw new UsernameNotFoundException("User with login " + email + " cannot be logged in!"); +// } else if (user instanceof LdapUser) { +// throw new UsernameNotFoundException("Ldap has not verified the user " + email + "!"); +// } +// +// return user.transformToLoggedUser(); + } +} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/LoginAttemptService.java b/src/main/java/com/netgrif/application/engine/authentication/service/LoginAttemptService.java similarity index 59% rename from src/main/java/com/netgrif/application/engine/auth/service/LoginAttemptService.java rename to src/main/java/com/netgrif/application/engine/authentication/service/LoginAttemptService.java index 8a6778a61c2..877f638760f 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/LoginAttemptService.java +++ b/src/main/java/com/netgrif/application/engine/authentication/service/LoginAttemptService.java @@ -1,14 +1,14 @@ -package com.netgrif.application.engine.auth.service; +package com.netgrif.application.engine.authentication.service; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; -import com.netgrif.application.engine.auth.service.interfaces.ILoginAttemptService; +import com.netgrif.application.engine.authentication.service.interfaces.ILoginAttemptService; import com.netgrif.application.engine.configuration.properties.SecurityLimitsProperties; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import javax.annotation.Nonnull; import java.util.concurrent.ExecutionException; @@ -16,43 +16,52 @@ @Service public class LoginAttemptService implements ILoginAttemptService { - @Autowired - private SecurityLimitsProperties securityLimitsProperties; - - private LoadingCache attemptsCache; + private final SecurityLimitsProperties securityLimitsProperties; + private final LoadingCache attemptsCache; public LoginAttemptService(SecurityLimitsProperties securityLimitsProperties) { - super(); - attemptsCache = CacheBuilder.newBuilder(). - expireAfterWrite(securityLimitsProperties.getLoginTimeout(), securityLimitsProperties.getLoginTimeoutUnit()).build(new CacheLoader<>() { - public Integer load(String key) { + this.securityLimitsProperties = securityLimitsProperties; + this.attemptsCache = CacheBuilder.newBuilder() + .expireAfterWrite(securityLimitsProperties.getLoginTimeout(), securityLimitsProperties.getLoginTimeoutUnit()).build(new CacheLoader<>() { + @Override + public Integer load(@Nonnull String key) { return 0; } }); } + // TODO: release/8.0.0 create test + /** + * todo javadoc + * */ public void loginSucceeded(String key) { attemptsCache.invalidate(key); } + /** + * todo javadoc + * */ public void loginFailed(String key) { - int attempts = 0; + int attempts; try { attempts = attemptsCache.get(key); } catch (ExecutionException e) { - log.error("Error reading login attempts cache for key " + key, e); + log.error("Error reading login attempts cache for key {}", key, e); attempts = 0; } attempts++; attemptsCache.put(key, attempts); } + /** + * todo javadoc + * */ public boolean isBlocked(String key) { try { return attemptsCache.get(key) >= securityLimitsProperties.getLoginAttempts(); } catch (ExecutionException e) { - log.error("Error reading login attempts cache for key " + key, e); + log.error("Error reading login attempts cache for key {}", key, e); return false; } } diff --git a/src/main/java/com/netgrif/application/engine/authentication/service/RegistrationService.java b/src/main/java/com/netgrif/application/engine/authentication/service/RegistrationService.java new file mode 100644 index 00000000000..54097ae9093 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/service/RegistrationService.java @@ -0,0 +1,379 @@ +package com.netgrif.application.engine.authentication.service; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.IdentityState; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authentication.service.interfaces.IRegistrationService; +import com.netgrif.application.engine.authentication.web.requestbodies.NewIdentityRequest; +import com.netgrif.application.engine.authentication.web.requestbodies.RegistrationRequest; +import com.netgrif.application.engine.authorization.domain.User; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.configuration.properties.ServerAuthProperties; +import com.netgrif.application.engine.event.events.authentication.IdentityRegistrationEvent; +import com.netgrif.application.engine.petrinet.domain.dataset.DateTimeField; +import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.transaction.NaeTransaction; +import groovy.lang.Closure; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.annotation.Lazy; +import org.springframework.data.mongodb.MongoTransactionManager; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +import java.math.BigInteger; +import java.security.SecureRandom; +import java.time.LocalDateTime; +import java.util.*; + +@Slf4j +@Service +public class RegistrationService implements IRegistrationService { + + private final BCryptPasswordEncoder bCryptPasswordEncoder; + private final IRoleService roleService; + private final IUserService userService; + private final MongoTransactionManager transactionManager; + private final ServerAuthProperties serverAuthProperties; + private final IIdentityService identityService; + private final ApplicationEventPublisher publisher; + + private static final String TOKEN_DELIMITER = ":"; + + public RegistrationService(BCryptPasswordEncoder bCryptPasswordEncoder, IRoleService roleService, + @Lazy IUserService userService, MongoTransactionManager transactionManager, + ServerAuthProperties serverAuthProperties, IIdentityService identityService, + ApplicationEventPublisher publisher) { + this.bCryptPasswordEncoder = bCryptPasswordEncoder; + this.roleService = roleService; + this.userService = userService; + this.transactionManager = transactionManager; + this.serverAuthProperties = serverAuthProperties; + this.identityService = identityService; + this.publisher = publisher; + } + + /** + * todo javadoc + * */ + @Override + public Identity createNewIdentity(NewIdentityRequest request) { + IdentityParams identityParams = IdentityParams.with() + .username(new TextField(request.email)) + .state(new EnumerationMapField(IdentityState.INVITED.name())) + .expirationDateTime(new DateTimeField(generateExpirationDate())) + .registrationToken(new TextField(generateTokenKey())) + .build(); + Optional identityOpt = identityService.findByUsername(request.email); + Identity identity; + + if (identityOpt.isPresent()) { + if (identityOpt.get().isActive()) { + return null; + } + log.info("Renewing old identity [{}]", request.email); + identity = identityService.update(identityOpt.get(), identityParams); + } else { + log.info("Creating new identity [{}]", request.email); + if (!TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<>(null) { + @Override + public Identity call() { + return doCreateNewIdentity(identityParams, request); + } + }) + .build(); + transaction.begin(); + identity = (Identity) transaction.getResultOfEvent(); + } else { + identity = doCreateNewIdentity(identityParams, request); + } + } + + return identity; + } + + private Identity doCreateNewIdentity(IdentityParams identityParams, NewIdentityRequest request) { + Identity identity = identityService.createWithDefaultUser(identityParams); + + if (request.roles != null && !request.roles.isEmpty()) { + roleService.assignRolesToActor(identity.getMainActorId(), request.roles); + } + + if (request.groups != null && !request.groups.isEmpty()) { + Optional userOpt = userService.findById(identity.getMainActorId()); + if (userOpt.isEmpty()) { + throw new IllegalStateException(String.format("Cannot find user with id [%s], that was just created.", + identity.getMainActorId())); + } + userService.addGroups(userOpt.get(), request.groups); + } + + publisher.publishEvent(new IdentityRegistrationEvent(identity)); + + return identity; + } + + /** + * todo javadoc + * */ + @Override + public Identity registerIdentity(RegistrationRequest registrationRequest) throws InvalidIdentityTokenException { + String email = decodeToken(registrationRequest.token)[0]; + log.info("Registering identity [{}]", email); + + Optional identityOpt = identityService.findByUsername(email); + if (identityOpt.isEmpty()) { + return null; + } + + Identity identity = identityOpt.get(); + + if (!TransactionSynchronizationManager.isSynchronizationActive()) { + Identity finalIdentity = identity; + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<>(null) { + @Override + public Identity call() { + return doRegisterIdentity(finalIdentity, registrationRequest); + } + }) + .build(); + transaction.begin(); + identity = (Identity) transaction.getResultOfEvent(); + } else { + identity = doRegisterIdentity(identity, registrationRequest); + } + + return identity; + } + + private Identity doRegisterIdentity(Identity identity, RegistrationRequest registrationRequest) { + IdentityParams identityParams = IdentityParams.with() + .password(new TextField(registrationRequest.password)) + .firstname(new TextField(registrationRequest.firstname)) + .lastname(new TextField(registrationRequest.lastname)) + .registrationToken(new TextField(null)) + .expirationDateTime(new DateTimeField(null)) + .state(new EnumerationMapField(IdentityState.ACTIVE.name())) + .build(); + + identity = identityService.encodePasswordAndUpdate(identity, identityParams); + + Optional userOpt = userService.findById(identity.getMainActorId()); + if (userOpt.isEmpty()) { + throw new IllegalStateException(String.format("Identity [%s] has no default user!", identity.getStringId())); + } + + UserParams userParams = UserParams.with() + .firstname(new TextField(registrationRequest.firstname)) + .lastname(new TextField(registrationRequest.lastname)) + .build(); + userService.update(userOpt.get(), userParams); + + return identity; + } + + /** + * todo javadoc + * */ + @Override + public boolean verifyToken(String token) { + try { + log.info("Verifying token: {}", token); + String[] tokenParts = decodeToken(token); + String email = tokenParts[0]; + String decodedToken = tokenParts[1]; + Optional identityOpt = identityService.findByUsername(email); + return identityOpt.isPresent() + && Objects.equals(identityOpt.get().getRegistrationToken(), decodedToken) + && identityOpt.get().getExpirationDate().isAfter(LocalDateTime.now()); + } catch (InvalidIdentityTokenException e) { + log.error(e.getMessage()); + return false; + } + } + + /** + * todo javadoc + * */ + @Override + public String generateTokenKey() { + return new BigInteger(256, new SecureRandom()).toString(32); + } + + /** + * todo javadoc + * */ + @Override + public String[] decodeToken(String token) throws InvalidIdentityTokenException { + if (token == null || token.isEmpty()) { + throw new InvalidIdentityTokenException(token); + } + byte[] decodedBytes; + + try { + decodedBytes = Base64.getDecoder().decode(token); + } catch (IllegalArgumentException exception) { + throw new InvalidIdentityTokenException(token); + } + String decodedString = new String(decodedBytes); + String[] parts = decodedString.split(TOKEN_DELIMITER); + + if (parts.length != 2 || !parts[0].contains("@")) { + throw new InvalidIdentityTokenException(token); + } + + return parts; + } + + /** + * todo javadoc + * */ + @Override + public String encodeToken(String email, String tokenKey) { + return Base64.getEncoder().encodeToString((email + TOKEN_DELIMITER + tokenKey).getBytes()); + } + + /** + * todo javadoc + * */ + @Override + @Scheduled(cron = "0 0 1 * * *") + public void removeExpiredIdentities() { + log.info("Removing expired unactivated identities"); + List expired = identityService.removeAllByStateAndExpirationDateBefore(IdentityState.INVITED, + LocalDateTime.now()); + log.info("Removed {} unactivated identities", expired.size()); + } + + /** + * todo javadoc + * */ + @Override + @Scheduled(cron = "0 0 1 * * *") + public void resetExpiredToken() { + log.info("Resetting expired identity tokens"); + List identities = identityService.findAllByStateAndExpirationDateBefore(IdentityState.BLOCKED, + LocalDateTime.now()); + if (identities.isEmpty()) { + log.info("There are none expired tokens. Everything is awesome."); + return; + } + if (!TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<>(null) { + @Override + public List call() { + return doResetExpiredToken(identities); + } + }) + .build(); + transaction.begin(); + } else { + doResetExpiredToken(identities); + } + + log.info("Reset {} expired identity tokens", identities.size()); + } + + private List doResetExpiredToken(List identities) { + identities.forEach(identity -> { + identityService.update(identity, IdentityParams.with() + .registrationToken(new TextField(null)) + .expirationDateTime(new DateTimeField(null)) + .build()); + }); + return identities; + } + + /** + * todo javadoc + * */ + @Override + public void changePassword(Identity identity, String newPassword) { + identityService.encodePasswordAndUpdate(identity, IdentityParams.with() + .password(new TextField(newPassword)) + .build()); + log.info("Changed password for identity {}.", identity.getUsername()); + } + + /** + * todo javadoc + * */ + @Override + public boolean matchesIdentityPassword(Identity identity, String passwordToCompare) { + return bCryptPasswordEncoder.matches(passwordToCompare, identity.getPassword()); + } + + /** + * todo javadoc + * */ + @Override + public Identity resetPassword(String email) { + log.info("Resetting password of {}", email); + + Optional identityOpt = identityService.findByUsername(email); + if (identityOpt.isEmpty() || !identityOpt.get().isActive()) { + String state = identityOpt.isEmpty() ? "Non-existing" : "Inactive"; + log.info("{} identity [{}] tried to reset his password", state, email); + return null; + } + IdentityParams params = IdentityParams.with() + .state(new EnumerationMapField(IdentityState.BLOCKED.name())) + .password(new TextField(null)) + .registrationToken(new TextField(generateTokenKey())) + .expirationDateTime(new DateTimeField(generateExpirationDate())) + .build(); + + return identityService.update(identityOpt.get(), params); + } + + /** + * todo javadoc + * */ + @Override + public Identity recover(String email, String newPassword) { + log.info("Recovering identity {}", email); + + Optional identityOpt = identityService.findByUsername(email); + if (identityOpt.isEmpty()) { + return null; + } + IdentityParams params = IdentityParams.with() + .state(new EnumerationMapField(IdentityState.ACTIVE.name())) + .password(new TextField(newPassword)) + .registrationToken(new TextField(null)) + .expirationDateTime(new DateTimeField(null)) + .build(); + + return identityService.encodePasswordAndUpdate(identityOpt.get(), params); + } + + /** + * todo javadoc + * */ + @Override + public LocalDateTime generateExpirationDate() { + return LocalDateTime.now().plusDays(serverAuthProperties.getTokenValidityPeriod()); + } + + /** + * todo javadoc + * */ + @Override + public boolean isPasswordSufficient(String password) { + // todo: release/8.0.0 is this enough? + return password.length() >= serverAuthProperties.getMinimalPasswordLength(); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authentication/service/UserDetailsServiceImpl.java b/src/main/java/com/netgrif/application/engine/authentication/service/UserDetailsServiceImpl.java new file mode 100644 index 00000000000..0aff4e53a0a --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/service/UserDetailsServiceImpl.java @@ -0,0 +1,62 @@ +package com.netgrif.application.engine.authentication.service; + +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authentication.service.interfaces.ILoginAttemptService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletRequest; + +@Slf4j +@Service +@RequiredArgsConstructor +public class UserDetailsServiceImpl implements UserDetailsService { + + protected final ApplicationEventPublisher publisher; + + protected final ILoginAttemptService loginAttemptService; + + protected final HttpServletRequest request; + + @Override + @Transactional(readOnly = true) + public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { + String ip = getClientIP(); + if (loginAttemptService.isBlocked(ip)) { + log.info("Identity {} with IP address {} is blocked.", email, ip); + throw new RuntimeException("blocked"); + } + + LoggedIdentity identity = getLoggedUser(email); + +// publisher.publishEvent(new UserLoginEvent(identity)); + + return identity; + } + + protected LoggedIdentity getLoggedUser(String email) throws UsernameNotFoundException { +// User user = userRepository.findByEmail(email); +// if (user == null) +// throw new UsernameNotFoundException("No user was found for login: " + email); +// if (user.getPassword() == null || user.getState() != IdentityState.ACTIVE) +// throw new UsernameNotFoundException("User with login " + email + " cannot be logged in!"); +// +// return user.transformToLoggedUser(); + return null; + } + + + protected String getClientIP() { + String xfHeader = request.getHeader("X-Forwarded-For"); + if (xfHeader == null) { + return request.getRemoteAddr(); + } + return xfHeader.split(",")[0]; + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/authentication/service/interfaces/IIdentityService.java b/src/main/java/com/netgrif/application/engine/authentication/service/interfaces/IIdentityService.java new file mode 100644 index 00000000000..302f53c30f8 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/service/interfaces/IIdentityService.java @@ -0,0 +1,31 @@ +package com.netgrif.application.engine.authentication.service.interfaces; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.IdentityState; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.workflow.service.interfaces.ICrudSystemCaseService; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +public interface IIdentityService extends ICrudSystemCaseService { + LoggedIdentity getLoggedIdentity(); + + Optional findByUsername(String username); + Optional findByLoggedIdentity(LoggedIdentity loggedIdentity); + boolean existsByUsername(String username); + Set findActorIds(String id); + List findAllByStateAndExpirationDateBefore(IdentityState state, LocalDateTime dateTime); + List findAll(); + + Identity createWithDefaultUser(IdentityParams params); + Identity encodePasswordAndCreate(IdentityParams params); + Identity encodePasswordAndUpdate(Identity identity, IdentityParams params); + Identity addAdditionalActor(Identity identity, String actorId); + Identity addAdditionalActors(Identity identity, Set actorIds); + + List removeAllByStateAndExpirationDateBefore(IdentityState state, LocalDateTime dateTime); +} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/ILdapUserRefService.java b/src/main/java/com/netgrif/application/engine/authentication/service/interfaces/ILdapUserRefService.java similarity index 64% rename from src/main/java/com/netgrif/application/engine/auth/service/interfaces/ILdapUserRefService.java rename to src/main/java/com/netgrif/application/engine/authentication/service/interfaces/ILdapUserRefService.java index 940491e502f..eef139cdafe 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/ILdapUserRefService.java +++ b/src/main/java/com/netgrif/application/engine/authentication/service/interfaces/ILdapUserRefService.java @@ -1,7 +1,6 @@ -package com.netgrif.application.engine.auth.service.interfaces; +package com.netgrif.application.engine.authentication.service.interfaces; -import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.ldap.domain.LdapUserRef; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; @@ -10,9 +9,9 @@ @ConditionalOnExpression("${nae.ldap.enabled:false}") public interface ILdapUserRefService { - IUser createUser(LdapUserRef ldapUser); +// IUser createUser(LdapUserRef ldapUser); - IUser updateById(Name id, IUser savedUser); +// IUser updateById(Name id, IUser savedUser); LdapUserRef findById(Name id); diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/ILoginAttemptService.java b/src/main/java/com/netgrif/application/engine/authentication/service/interfaces/ILoginAttemptService.java similarity index 67% rename from src/main/java/com/netgrif/application/engine/auth/service/interfaces/ILoginAttemptService.java rename to src/main/java/com/netgrif/application/engine/authentication/service/interfaces/ILoginAttemptService.java index f8dbfba3a38..9c2ca804809 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/ILoginAttemptService.java +++ b/src/main/java/com/netgrif/application/engine/authentication/service/interfaces/ILoginAttemptService.java @@ -1,4 +1,4 @@ -package com.netgrif.application.engine.auth.service.interfaces; +package com.netgrif.application.engine.authentication.service.interfaces; public interface ILoginAttemptService { diff --git a/src/main/java/com/netgrif/application/engine/authentication/service/interfaces/IRegistrationService.java b/src/main/java/com/netgrif/application/engine/authentication/service/interfaces/IRegistrationService.java new file mode 100644 index 00000000000..0d2aea4c32b --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/service/interfaces/IRegistrationService.java @@ -0,0 +1,39 @@ +package com.netgrif.application.engine.authentication.service.interfaces; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.service.InvalidIdentityTokenException; +import com.netgrif.application.engine.authentication.web.requestbodies.NewIdentityRequest; +import com.netgrif.application.engine.authentication.web.requestbodies.RegistrationRequest; + +import java.time.LocalDateTime; + +public interface IRegistrationService { + + void removeExpiredIdentities(); + + void resetExpiredToken(); + + void changePassword(Identity identity, String newPassword); + + boolean verifyToken(String token); + + Identity createNewIdentity(NewIdentityRequest newUser); + + Identity registerIdentity(RegistrationRequest registrationRequest) throws InvalidIdentityTokenException; + + boolean matchesIdentityPassword(Identity identity, String passwordToCompare); + + Identity resetPassword(String email); + + Identity recover(String email, String newPassword); + + String generateTokenKey(); + + String[] decodeToken(String token) throws InvalidIdentityTokenException; + + String encodeToken(String email, String tokenKey); + + LocalDateTime generateExpirationDate(); + + boolean isPasswordSufficient(String password); +} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java b/src/main/java/com/netgrif/application/engine/authentication/web/AuthenticationController.java similarity index 53% rename from src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java rename to src/main/java/com/netgrif/application/engine/authentication/web/AuthenticationController.java index 09422577de5..f9db74a5d20 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java +++ b/src/main/java/com/netgrif/application/engine/authentication/web/AuthenticationController.java @@ -1,16 +1,15 @@ -package com.netgrif.application.engine.auth.web; - -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.domain.RegisteredUser; -import com.netgrif.application.engine.auth.service.InvalidUserTokenException; -import com.netgrif.application.engine.auth.service.UserDetailsServiceImpl; -import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.auth.web.requestbodies.ChangePasswordRequest; -import com.netgrif.application.engine.auth.web.requestbodies.NewUserRequest; -import com.netgrif.application.engine.auth.web.requestbodies.RegistrationRequest; -import com.netgrif.application.engine.auth.web.responsebodies.User; -import com.netgrif.application.engine.auth.web.responsebodies.UserResource; +package com.netgrif.application.engine.authentication.web; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authentication.service.InvalidIdentityTokenException; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authentication.service.interfaces.IRegistrationService; +import com.netgrif.application.engine.authentication.web.requestbodies.ChangePasswordRequest; +import com.netgrif.application.engine.authentication.web.requestbodies.NewIdentityRequest; +import com.netgrif.application.engine.authentication.web.requestbodies.RegistrationRequest; +import com.netgrif.application.engine.authentication.web.responsebodies.IdentityDTO; +import com.netgrif.application.engine.authentication.web.responsebodies.IdentityResource; import com.netgrif.application.engine.configuration.properties.ServerAuthProperties; import com.netgrif.application.engine.mail.interfaces.IMailAttemptService; import com.netgrif.application.engine.mail.interfaces.IMailService; @@ -20,11 +19,12 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; @@ -33,10 +33,11 @@ import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.Base64; -import java.util.Locale; +import java.util.Optional; @Slf4j @RestController +@RequiredArgsConstructor @RequestMapping("/api/auth") @ConditionalOnProperty( value = "nae.auth.web.enabled", @@ -46,66 +47,62 @@ @Tag(name = "Authentication") public class AuthenticationController { - @Autowired - private IRegistrationService registrationService; + private final IRegistrationService registrationService; - @Autowired - private UserDetailsServiceImpl userDetailsService; + private final IMailService mailService; - @Autowired - private IMailService mailService; + private final IMailAttemptService mailAttemptService; - @Autowired - private IUserService userService; + private final ServerAuthProperties serverAuthProperties; - @Autowired - private IMailAttemptService mailAttemptService; + private final ISecurityContextService securityContextService; - @Autowired - private ServerAuthProperties serverAuthProperties; + private final IIdentityService identityService; - @Autowired - private ISecurityContextService securityContextService; - - @Operation(summary = "New user registration") + @Operation(summary = "New identity registration") @PostMapping(value = "/signup", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public MessageResource signup(@RequestBody RegistrationRequest regRequest) { try { - String email = registrationService.decodeToken(regRequest.token)[0]; - if (!registrationService.verifyToken(regRequest.token)) - return MessageResource.errorMessage("Registration of " + email + " has failed! Invalid token!"); + if (!registrationService.verifyToken(regRequest.token)) { + String email = registrationService.decodeToken(regRequest.token)[0]; + return MessageResource.errorMessage(String.format("Registration of %s has failed! Invalid token!", email)); + } regRequest.password = new String(Base64.getDecoder().decode(regRequest.password)); - RegisteredUser user = registrationService.registerUser(regRequest); - if (user == null) - return MessageResource.errorMessage("Registration of " + email + " has failed! No user with this email was found."); + Identity identity = registrationService.registerIdentity(regRequest); + if (identity == null) { + String email = registrationService.decodeToken(regRequest.token)[0]; + return MessageResource.errorMessage(String.format("Registration of %s has failed! No identity with this email was found.", email)); + } return MessageResource.successMessage("Registration complete"); - } catch (InvalidUserTokenException e) { + } catch (InvalidIdentityTokenException e) { log.error(e.getMessage()); return MessageResource.errorMessage("Invalid token!"); } } - @Operation(summary = "Send invitation to a new user", security = {@SecurityRequirement(name = "BasicAuth")}) + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") + @Operation(summary = "Send invitation to a new identity", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/invite", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public MessageResource invite(@RequestBody NewUserRequest newUserRequest, Authentication auth) { + public MessageResource invite(@RequestBody NewIdentityRequest newIdentityRequest, Authentication auth) { try { - if (!serverAuthProperties.isOpenRegistration() && (auth == null || !((LoggedUser) auth.getPrincipal()).getSelfOrImpersonated().isAdmin())) { - return MessageResource.errorMessage("Only admin can invite new users!"); + if (!serverAuthProperties.isOpenRegistration()) { + return MessageResource.errorMessage("Registration is turned off."); } - newUserRequest.email = URLDecoder.decode(newUserRequest.email, StandardCharsets.UTF_8.name()); - if (mailAttemptService.isBlocked(newUserRequest.email)) { + newIdentityRequest.email = URLDecoder.decode(newIdentityRequest.email, StandardCharsets.UTF_8); + if (mailAttemptService.isBlocked(newIdentityRequest.email)) { return MessageResource.successMessage("Done"); } - RegisteredUser user = registrationService.createNewUser(newUserRequest); - if (user == null) + Identity identity = registrationService.createNewIdentity(newIdentityRequest); + if (identity == null) { return MessageResource.successMessage("Done"); - mailService.sendRegistrationEmail(user); + } + mailService.sendRegistrationEmail(identity); + mailAttemptService.mailAttempt(newIdentityRequest.email); - mailAttemptService.mailAttempt(newUserRequest.email); return MessageResource.successMessage("Done"); } catch (IOException | TemplateException | MessagingException e) { log.error(e.toString()); @@ -117,11 +114,12 @@ public MessageResource invite(@RequestBody NewUserRequest newUserRequest, Authen @PostMapping(value = "/token/verify", consumes = MediaType.TEXT_PLAIN_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public MessageResource verifyToken(@RequestBody String token) { try { - if (registrationService.verifyToken(token)) + if (registrationService.verifyToken(token)) { return MessageResource.successMessage(registrationService.decodeToken(token)[0]); - else + } else { return MessageResource.errorMessage("Invalid token!"); - } catch (InvalidUserTokenException e) { + } + } catch (InvalidIdentityTokenException e) { log.error(e.getMessage()); return MessageResource.errorMessage("Invalid token!"); } @@ -130,14 +128,21 @@ public MessageResource verifyToken(@RequestBody String token) { @Operation(summary = "Verify validity of an authentication token") @GetMapping(value = "/verify", produces = MediaTypes.HAL_JSON_VALUE) public MessageResource verifyAuthToken(Authentication auth) { - LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); - return MessageResource.successMessage("Auth Token successfully verified, for user [" + loggedUser.getId() + "] " + loggedUser.getFullName()); + LoggedIdentity identity = (LoggedIdentity) auth.getPrincipal(); + return MessageResource.successMessage(String.format("Auth Token successfully verified, for identity [%s] %s", + identity.getIdentityId(), identity.getUsername())); } @Operation(summary = "Login to the system", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/login", produces = MediaTypes.HAL_JSON_VALUE) - public UserResource login(Authentication auth, Locale locale) { - return new UserResource(new User(userService.findByAuth(auth)), "profile"); + public IdentityResource login(Authentication auth) { + LoggedIdentity loggedIdentity = (LoggedIdentity) auth.getPrincipal(); + Optional identityOpt = identityService.findByUsername(loggedIdentity.getUsername()); + if (identityOpt.isEmpty()) { + log.error("Unexpected: identity [{}] was not found after authentication", loggedIdentity.getUsername()); + throw new IllegalStateException("Login has failed"); + } + return new IdentityResource(new IdentityDTO(identityOpt.get(), loggedIdentity.getActiveActorId()), "profile"); } @Operation(summary = "Reset password") @@ -147,14 +152,12 @@ public MessageResource resetPassword(@RequestBody String recoveryEmail) { return MessageResource.successMessage("Done"); } try { - RegisteredUser user = registrationService.resetPassword(recoveryEmail); - if (user != null) { - mailService.sendPasswordResetEmail(user); - mailAttemptService.mailAttempt(user.getEmail()); - return MessageResource.successMessage("Done"); - } else { - return MessageResource.successMessage("Done"); + Identity identity = registrationService.resetPassword(recoveryEmail); + if (identity != null) { + mailService.sendPasswordResetEmail(identity); + mailAttemptService.mailAttempt(identity.getUsername()); } + return MessageResource.successMessage("Done"); } catch (MessagingException | IOException | TemplateException e) { log.error(e.toString()); return MessageResource.errorMessage("Failed"); @@ -165,13 +168,17 @@ public MessageResource resetPassword(@RequestBody String recoveryEmail) { @PostMapping(value = "/recover", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public MessageResource recoverAccount(@RequestBody RegistrationRequest request) { try { - if (!registrationService.verifyToken(request.token)) + if (!registrationService.verifyToken(request.token)) { return MessageResource.errorMessage("Invalid token!"); - RegisteredUser user = registrationService.recover(registrationService.decodeToken(request.token)[0], new String(Base64.getDecoder().decode(request.password))); - if (user == null) + } + String email = registrationService.decodeToken(request.token)[0]; + String password = new String(Base64.getDecoder().decode(request.password)); + Identity identity = registrationService.recover(email, password); + if (identity == null) { return MessageResource.errorMessage("Recovery of account has failed!"); + } return MessageResource.successMessage("Account is successfully recovered. You can login now."); - } catch (InvalidUserTokenException e) { + } catch (InvalidIdentityTokenException e) { log.error(e.getMessage()); return MessageResource.errorMessage("Invalid token!"); } @@ -181,8 +188,11 @@ public MessageResource recoverAccount(@RequestBody RegistrationRequest request) @PostMapping(value = "/changePassword", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public MessageResource changePassword(Authentication auth, @RequestBody ChangePasswordRequest request) { try { - RegisteredUser user = (RegisteredUser) userService.findByEmail(request.login); - if (user == null || request.password == null || request.newPassword == null) { + if (request.password == null || request.newPassword == null) { + return MessageResource.errorMessage("Insufficient password!"); + } + Optional identityOpt = identityService.findByUsername(request.login); + if (identityOpt.isEmpty()) { return MessageResource.errorMessage("Incorrect login!"); } @@ -191,12 +201,11 @@ public MessageResource changePassword(Authentication auth, @RequestBody ChangePa return MessageResource.errorMessage("Insufficient password!"); } - String password = new String(Base64.getDecoder().decode(request.password)); - if (registrationService.stringMatchesUserPassword(user, password)) { - registrationService.changePassword(user, newPassword); - securityContextService.saveToken(((LoggedUser) auth.getPrincipal()).getId()); - securityContextService.reloadSecurityContext((LoggedUser) auth.getPrincipal()); - + String currentPassword = new String(Base64.getDecoder().decode(request.password)); + if (registrationService.matchesIdentityPassword(identityOpt.get(), currentPassword)) { + registrationService.changePassword(identityOpt.get(), newPassword); + securityContextService.saveToken(((LoggedIdentity) auth.getPrincipal()).getIdentityId()); + securityContextService.reloadSecurityContext((LoggedIdentity) auth.getPrincipal()); } else { return MessageResource.errorMessage("Incorrect password!"); } diff --git a/src/main/java/com/netgrif/application/engine/authentication/web/IdentityController.java b/src/main/java/com/netgrif/application/engine/authentication/web/IdentityController.java new file mode 100644 index 00000000000..0a31569ff5c --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/web/IdentityController.java @@ -0,0 +1,96 @@ +package com.netgrif.application.engine.authentication.web; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authentication.web.responsebodies.IdentityDTO; +import com.netgrif.application.engine.authentication.web.responsebodies.IdentityResource; +import com.netgrif.application.engine.authorization.service.interfaces.IApplicationAuthorizationService; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.settings.domain.Preferences; +import com.netgrif.application.engine.settings.service.IPreferencesService; +import com.netgrif.application.engine.settings.web.PreferencesResource; +import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.hateoas.MediaTypes; +import org.springframework.http.MediaType; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +import java.util.Objects; +import java.util.Optional; + +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/identity") +@ConditionalOnProperty( + value = "nae.identity.web.enabled", + havingValue = "true", + matchIfMissing = true +) +@Tag(name = "Identity") +public class IdentityController { + + private final IIdentityService identityService; + private final ISessionManagerService sessionManagerService; + private final IApplicationAuthorizationService authorizationService; + private final IPreferencesService preferencesService; + + // TODO: release/8.0.0 any more endpoints? + + @Operation(summary = "Get identity by id", security = {@SecurityRequirement(name = "BasicAuth")}) + @GetMapping(value = "/{id}", produces = MediaTypes.HAL_JSON_VALUE) + public IdentityResource getIdentity(@PathVariable("id") String identityId) { + LoggedIdentity loggedIdentity = sessionManagerService.getLoggedIdentity(); + if (!Objects.equals(loggedIdentity.getIdentityId(), identityId) && authorizationService.hasApplicationRole("admin")) { + log.info("Identity [{}] is trying to get different identity with ID [{}]", loggedIdentity.getUsername(), identityId); + throw new IllegalArgumentException(String.format("Could not find identity with id [%s]", identityId)); + } + Optional identityOpt = identityService.findById(identityId); + if (identityOpt.isEmpty()) { + throw new IllegalArgumentException(String.format("Could not find identity with id [%s]", identityId)); + } + return new IdentityResource(new IdentityDTO(identityOpt.get(), loggedIdentity.getActiveActorId()), "profile"); + } + + @Operation(summary = "Get logged identity", security = {@SecurityRequirement(name = "BasicAuth")}) + @GetMapping(value = "/me", produces = MediaTypes.HAL_JSON_VALUE) + public IdentityResource getLoggedIdentity(Authentication auth) { + LoggedIdentity loggedIdentity = (LoggedIdentity) auth.getPrincipal(); + return new IdentityResource(new IdentityDTO(loggedIdentity), "me"); + } + + @Operation(summary = "Get identity's preferences", security = {@SecurityRequirement(name = "BasicAuth")}) + @GetMapping(value = "/preferences", produces = MediaTypes.HAL_JSON_VALUE) + public PreferencesResource preferences() { + LoggedIdentity loggedIdentity = sessionManagerService.getLoggedIdentity(); + Optional preferencesOpt = preferencesService.get(loggedIdentity.getIdentityId()); + + if (preferencesOpt.isEmpty()) { + preferencesOpt = Optional.of(new Preferences(loggedIdentity.getIdentityId())); + } + + return new PreferencesResource(preferencesOpt.get()); + } + + @Operation(summary = "Set identity's preferences", security = {@SecurityRequirement(name = "BasicAuth")}) + @PostMapping(value = "/preferences", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) + public MessageResource savePreferences(@RequestBody Preferences preferences) { + LoggedIdentity loggedIdentity = sessionManagerService.getLoggedIdentity(); + try { + preferences.setIdentityId(loggedIdentity.getIdentityId()); + preferencesService.save(preferences); + return MessageResource.successMessage("Identity's preferences saved"); + } catch (Exception e) { + log.error("Saving identity's [{}] preferences failed with message: {}", loggedIdentity.getUsername(), + e.getMessage(), e); + return MessageResource.errorMessage("Saving identity's preferences failed"); + } + } +} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserControllerAdvice.java b/src/main/java/com/netgrif/application/engine/authentication/web/IdentityControllerAdvice.java similarity index 73% rename from src/main/java/com/netgrif/application/engine/auth/web/UserControllerAdvice.java rename to src/main/java/com/netgrif/application/engine/authentication/web/IdentityControllerAdvice.java index 020df490d97..b1e04da40b9 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserControllerAdvice.java +++ b/src/main/java/com/netgrif/application/engine/authentication/web/IdentityControllerAdvice.java @@ -1,4 +1,4 @@ -package com.netgrif.application.engine.auth.web; +package com.netgrif.application.engine.authentication.web; import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; import lombok.extern.slf4j.Slf4j; @@ -9,14 +9,14 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; @Slf4j -@RestControllerAdvice(assignableTypes = {UserController.class}) -public class UserControllerAdvice { +@RestControllerAdvice(assignableTypes = {IdentityController.class}) +public class IdentityControllerAdvice { @ExceptionHandler(NumberFormatException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) public @ResponseBody MessageResource handleException(NumberFormatException e) { - log.error("Long could not be parsed from request. " + e.getMessage(), e); + log.error("Long could not be parsed from request. {}", e.getMessage(), e); return MessageResource.errorMessage(e.getMessage()); } } diff --git a/src/main/java/com/netgrif/application/engine/authentication/web/PublicIdentityController.java b/src/main/java/com/netgrif/application/engine/authentication/web/PublicIdentityController.java new file mode 100644 index 00000000000..eadfd6aec79 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/web/PublicIdentityController.java @@ -0,0 +1,65 @@ +package com.netgrif.application.engine.authentication.web; + +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authentication.domain.PublicStrategy; +import com.netgrif.application.engine.authentication.domain.throwable.WrongPublicConfigurationException; +import com.netgrif.application.engine.authentication.web.responsebodies.IdentityDTO; +import com.netgrif.application.engine.authentication.web.responsebodies.IdentityResource; +import com.netgrif.application.engine.configuration.PublicViewProperties; +import com.netgrif.application.engine.settings.domain.Preferences; +import com.netgrif.application.engine.settings.web.PreferencesResource; +import com.netgrif.application.engine.startup.AnonymousIdentityRunner; +import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.hateoas.MediaTypes; +import org.springframework.http.MediaType; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.*; + +@Slf4j +@RestController +@RequiredArgsConstructor +@ConditionalOnProperty( + value = "nae.public.identity.web.enabled", + havingValue = "true", + matchIfMissing = true +) +@Tag(name = "Public Identity Controller") +@RequestMapping("/api/public/identity") +public class PublicIdentityController { + + private final IdentityController identityController; + private final PublicViewProperties publicViewProperties; + + + @Operation(summary = "Get identity's preferences") + @GetMapping(value = "/preferences", produces = MediaTypes.HAL_JSON_VALUE) + public PreferencesResource preferences() { + return identityController.preferences(); + } + + @Operation(summary = "Set identity's preferences") + @PostMapping(value = "/preferences", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) + public MessageResource savePreferences(@RequestBody Preferences preferences) throws WrongPublicConfigurationException { + if (publicViewProperties.getStrategy().equals(PublicStrategy.SIMPLE)) { + throw new WrongPublicConfigurationException(String.format("Cannot save preferences with configured [%s] public strategy!", + PublicStrategy.SIMPLE.name())); + } + return identityController.savePreferences(preferences); + } + + @Operation(summary = "Get logged anonymous identity", security = {@SecurityRequirement(name = "BasicAuth")}) + @GetMapping(value = "/me", produces = MediaTypes.HAL_JSON_VALUE) + public IdentityResource getLoggedIdentity() { + LoggedIdentity loggedIdentity = (LoggedIdentity) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + if (loggedIdentity.getProperties().containsKey(AnonymousIdentityRunner.getAnonymousFlag())) { + return new IdentityResource(new IdentityDTO(loggedIdentity), "me"); + } + return null; + } +} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/ChangePasswordRequest.java b/src/main/java/com/netgrif/application/engine/authentication/web/requestbodies/ChangePasswordRequest.java similarity index 83% rename from src/main/java/com/netgrif/application/engine/auth/web/requestbodies/ChangePasswordRequest.java rename to src/main/java/com/netgrif/application/engine/authentication/web/requestbodies/ChangePasswordRequest.java index 70209845b0b..029716bd206 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/ChangePasswordRequest.java +++ b/src/main/java/com/netgrif/application/engine/authentication/web/requestbodies/ChangePasswordRequest.java @@ -1,4 +1,4 @@ -package com.netgrif.application.engine.auth.web.requestbodies; +package com.netgrif.application.engine.authentication.web.requestbodies; public class ChangePasswordRequest { diff --git a/src/main/java/com/netgrif/application/engine/authentication/web/requestbodies/NewIdentityRequest.java b/src/main/java/com/netgrif/application/engine/authentication/web/requestbodies/NewIdentityRequest.java new file mode 100644 index 00000000000..d530a32a3e9 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/web/requestbodies/NewIdentityRequest.java @@ -0,0 +1,16 @@ +package com.netgrif.application.engine.authentication.web.requestbodies; + +import lombok.Data; + +import java.util.Set; + +@Data +public class NewIdentityRequest { + + public String email; + public Set groups; + public Set roles; + + public NewIdentityRequest() { + } +} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/RegistrationRequest.java b/src/main/java/com/netgrif/application/engine/authentication/web/requestbodies/RegistrationRequest.java similarity index 50% rename from src/main/java/com/netgrif/application/engine/auth/web/requestbodies/RegistrationRequest.java rename to src/main/java/com/netgrif/application/engine/authentication/web/requestbodies/RegistrationRequest.java index a2594c6609f..be0838813ca 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/RegistrationRequest.java +++ b/src/main/java/com/netgrif/application/engine/authentication/web/requestbodies/RegistrationRequest.java @@ -1,11 +1,11 @@ -package com.netgrif.application.engine.auth.web.requestbodies; +package com.netgrif.application.engine.authentication.web.requestbodies; public class RegistrationRequest { public String token; - public String name; - public String surname; + public String firstname; + public String lastname; public String password; public RegistrationRequest() { diff --git a/src/main/java/com/netgrif/application/engine/authentication/web/responsebodies/IdentityDTO.java b/src/main/java/com/netgrif/application/engine/authentication/web/responsebodies/IdentityDTO.java new file mode 100644 index 00000000000..798ffe6bf9a --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/web/responsebodies/IdentityDTO.java @@ -0,0 +1,37 @@ +package com.netgrif.application.engine.authentication.web.responsebodies; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import lombok.Data; + +@Data +public class IdentityDTO { + + private String id; + + private String username; + + private String firstname; + + private String lastname; + + private String fullName; + + private String activeActorId; + + public IdentityDTO(Identity identity, String activeActorId) { + this.id = identity.getStringId(); + this.username = identity.getUsername(); + this.firstname = identity.getFirstname(); + this.lastname = identity.getLastname(); + this.fullName = identity.getFullName(); + this.activeActorId = activeActorId; + } + + public IdentityDTO(LoggedIdentity loggedIdentity) { + this.id = loggedIdentity.getIdentityId(); + this.username = loggedIdentity.getUsername(); + this.fullName = loggedIdentity.getFullName(); + this.activeActorId = loggedIdentity.getActiveActorId(); + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/authentication/web/responsebodies/IdentityResource.java b/src/main/java/com/netgrif/application/engine/authentication/web/responsebodies/IdentityResource.java new file mode 100644 index 00000000000..c0844f52c0f --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authentication/web/responsebodies/IdentityResource.java @@ -0,0 +1,28 @@ +package com.netgrif.application.engine.authentication.web.responsebodies; + + +import com.netgrif.application.engine.authentication.web.IdentityController; +import com.netgrif.application.engine.authorization.web.RBACController; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; + +import java.util.ArrayList; +import java.util.Objects; + +public class IdentityResource extends EntityModel { + + public IdentityResource(IdentityDTO content, String selfRel) { + super(content, new ArrayList<>()); + buildLinks(selfRel); + } + + private void buildLinks(String selfRel) { + WebMvcLinkBuilder getLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(IdentityController.class) + .getIdentity(Objects.requireNonNull(getContent()).getId())); + add(selfRel.equalsIgnoreCase("profile") ? getLink.withSelfRel() : getLink.withRel("profile")); + + WebMvcLinkBuilder roleLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(RBACController.class) + .assignRolesToActor(getContent().getId(), null)); + add(selfRel.equalsIgnoreCase("assignRolesToActor") ? roleLink.withSelfRel() : roleLink.withRel("assignRolesToActor")); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/Actor.java b/src/main/java/com/netgrif/application/engine/authorization/domain/Actor.java new file mode 100644 index 00000000000..fee50e49b2d --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/Actor.java @@ -0,0 +1,24 @@ +package com.netgrif.application.engine.authorization.domain; + +import com.netgrif.application.engine.authorization.domain.constants.ActorConstants; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.SystemCase; +import lombok.Getter; + +import java.util.List; + +@Getter +public abstract class Actor extends SystemCase { + + public Actor(Case actorCase) { + super(actorCase); + } + + public abstract String getName(); + + public List getGroupIds() { + return ((CaseField) getCase().getDataSet().get(ActorConstants.GROUPS_FIELD_ID)).getRawValue(); + } + +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/ApplicationRole.java b/src/main/java/com/netgrif/application/engine/authorization/domain/ApplicationRole.java new file mode 100644 index 00000000000..dc0105a9a7c --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/ApplicationRole.java @@ -0,0 +1,56 @@ +package com.netgrif.application.engine.authorization.domain; + +import com.netgrif.application.engine.authorization.service.factory.ApplicationRoleAssignmentFactory; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.bson.types.ObjectId; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.security.core.GrantedAuthority; + +import java.util.HashMap; + +@Data +@Document(collection = "role") +@EqualsAndHashCode(callSuper = true) +public class ApplicationRole extends Role implements GrantedAuthority { + + @Indexed + private String applicationId; + + public ApplicationRole() { + this(new ObjectId(), null, null); + } + + public ApplicationRole(String importId, String applicationId) { + this(new ObjectId(), importId, applicationId); + } + + public ApplicationRole(ObjectId id, String importId, String applicationId) { + super(id); + this.importId = importId; + this.events = new HashMap<>(); // application role has no events for now, can be changed in future releases + this.applicationId = applicationId; + } + + + @Override + public Class getAssignmentFactoryClass() { + return ApplicationRoleAssignmentFactory.class; + } + + @Override + public String getTitleAsString() { + return String.format("APPROLE[%s-%s]", applicationId, importId); + } + + @Override + public String toString() { + return getTitleAsString(); + } + + @Override + public String getAuthority() { + return importId; + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/ApplicationRoleAssignment.java b/src/main/java/com/netgrif/application/engine/authorization/domain/ApplicationRoleAssignment.java new file mode 100644 index 00000000000..abb0b883972 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/ApplicationRoleAssignment.java @@ -0,0 +1,14 @@ +package com.netgrif.application.engine.authorization.domain; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +@Data +@Document(collection = "roleAssignment") +@EqualsAndHashCode(callSuper = true) +public class ApplicationRoleAssignment extends RoleAssignment { + @Indexed + private String applicationId; +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/CaseRole.java b/src/main/java/com/netgrif/application/engine/authorization/domain/CaseRole.java new file mode 100644 index 00000000000..00fd013691b --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/CaseRole.java @@ -0,0 +1,49 @@ +package com.netgrif.application.engine.authorization.domain; + +import com.netgrif.application.engine.authorization.service.factory.CaseRoleAssignmentFactory; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.bson.types.ObjectId; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.HashMap; + +@Data +@Document(collection = "role") +@EqualsAndHashCode(callSuper = true) +public class CaseRole extends Role { + + @Indexed + private String caseId; + + public CaseRole() { + this(new ObjectId(), null, null); + } + + public CaseRole(String importId, String caseId) { + this(new ObjectId(), importId, caseId); + } + + public CaseRole(ObjectId id, String importId, String caseId) { + super(id); + this.importId = importId; + this.caseId = caseId; + this.events = new HashMap<>(); // case role has no events for now, can be changed in future releases + } + + @Override + public Class getAssignmentFactoryClass() { + return CaseRoleAssignmentFactory.class; + } + + @Override + public String getTitleAsString() { + return String.format("CASEROLE[%s-%s]", caseId, importId); + } + + @Override + public String toString() { + return getTitleAsString(); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/CaseRoleAssignment.java b/src/main/java/com/netgrif/application/engine/authorization/domain/CaseRoleAssignment.java new file mode 100644 index 00000000000..311026578e0 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/CaseRoleAssignment.java @@ -0,0 +1,14 @@ +package com.netgrif.application.engine.authorization.domain; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +@Data +@Document(collection = "roleAssignment") +@EqualsAndHashCode(callSuper = true) +public class CaseRoleAssignment extends RoleAssignment { + @Indexed + private String caseId; +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/Group.java b/src/main/java/com/netgrif/application/engine/authorization/domain/Group.java new file mode 100644 index 00000000000..4e85c602f7f --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/Group.java @@ -0,0 +1,34 @@ +package com.netgrif.application.engine.authorization.domain; + +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.workflow.domain.Case; + +import java.util.List; + +public class Group extends Actor { + + public Group(Case groupCase) { + super(groupCase); + } + + @Override + protected CanInitializeOutcome canInitialize(Case groupCase) { + return new CanInitializeOutcome("Provided group case is of different process", + groupCase.getProcessIdentifier().equals(GroupConstants.PROCESS_IDENTIFIER)); + } + + @Override + public String getName() { + return (String) getCase().getDataSet().get(GroupConstants.NAME_FIELD_ID).getRawValue(); + } + + public String getParentGroupId() { + List parentGroupIdAsList = ((CaseField) getCase().getDataSet().get(GroupConstants.PARENT_GROUP_FIELD_ID)).getRawValue(); + if (parentGroupIdAsList != null && !parentGroupIdAsList.isEmpty()) { + return parentGroupIdAsList.get(0); + } + return null; + } + +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/ProcessRole.java b/src/main/java/com/netgrif/application/engine/authorization/domain/ProcessRole.java new file mode 100755 index 00000000000..4f08e010981 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/ProcessRole.java @@ -0,0 +1,76 @@ +package com.netgrif.application.engine.authorization.domain; + +import com.netgrif.application.engine.authorization.service.factory.ProcessRoleAssignmentFactory; +import com.netgrif.application.engine.petrinet.domain.I18nString; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.bson.types.ObjectId; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.*; + +@Data +@Document(collection = "role") +@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false) +public class ProcessRole extends Role { + + public static final String DEFAULT_ROLE = "default"; + public static final String ANONYMOUS_ROLE = "anonymous"; + + private I18nString title; + private I18nString description; + + public ProcessRole(ObjectId id, String importId) { + super(id); + this.importId = importId; + this.events = new HashMap<>(); + } + + public ProcessRole(String importId) { + this(new ObjectId(), importId); + } + + public ProcessRole() { + this(new ObjectId(), null); + } + + @Override + public Class getAssignmentFactoryClass() { + return ProcessRoleAssignmentFactory.class; + } + + @Override + public String getTitleAsString() { + return this.title != null ? this.title.getDefaultValue() : this.importId; + } + + @EqualsAndHashCode.Include + public String getStringId() { + return id.toString(); + } + + public void setStringId(String id) { + this.id = new ObjectId(id); + } + + public String getLocalisedName(Locale locale) { + if (title == null) { + return null; + } + return title.getTranslation(locale); + } + + @Override + public String toString() { + return getTitleAsString(); + } + + @Override + public ProcessRole clone() { + ProcessRole clone = new ProcessRole(this.importId); + clone.setStringId(this.getStringId()); + clone.setTitle(this.title == null ? null : this.title.clone()); + clone.setDescription(this.description == null ? null : this.description.clone()); + return clone; + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/ProcessRoleAssignment.java b/src/main/java/com/netgrif/application/engine/authorization/domain/ProcessRoleAssignment.java new file mode 100644 index 00000000000..f5787a2698a --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/ProcessRoleAssignment.java @@ -0,0 +1,20 @@ +package com.netgrif.application.engine.authorization.domain; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.data.mongodb.core.mapping.Document; + +@Data +@Document(collection = "roleAssignment") +@EqualsAndHashCode(callSuper = true) +public class ProcessRoleAssignment extends RoleAssignment { + private Session session; + + public ProcessRoleAssignment() { + this(Session.forever()); + } + + public ProcessRoleAssignment(Session session) { + this.session = session; + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/Role.java b/src/main/java/com/netgrif/application/engine/authorization/domain/Role.java new file mode 100644 index 00000000000..f61602add37 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/Role.java @@ -0,0 +1,85 @@ +package com.netgrif.application.engine.authorization.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.netgrif.application.engine.importer.model.EventType; +import com.netgrif.application.engine.importer.model.RoleEventType; +import com.netgrif.application.engine.petrinet.domain.Imported; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; +import com.netgrif.application.engine.petrinet.domain.events.RoleEvent; +import com.netgrif.application.engine.utils.UniqueKeyMapWrapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +@Data +@Document +@EqualsAndHashCode(callSuper = true) +public abstract class Role extends Imported { + // TODO: release/8.0.0 indexed import id + @Id + protected ObjectId id; + @JsonIgnore + protected Map events; + protected UniqueKeyMapWrapper properties; + + /** + * todo javadoc + * */ + public abstract Class getAssignmentFactoryClass(); + + /** + * todo javadoc + * */ + public abstract String getTitleAsString(); + + + public Role(ObjectId id) { + this.id = id; + } + + public Role() { + this(new ObjectId()); + } + + public String getStringId() { + return this.id.toString(); + } + + public List getPreAssignActions() { + return getPreActions(EventType.ASSIGN); + } + + public List getPostAssignActions() { + return getPostActions(EventType.ASSIGN); + } + + public List getPreCancelActions() { + return getPreActions(EventType.CANCEL); + } + + public List getPostCancelActions() { + return getPostActions(EventType.CANCEL); + } + + private List getPreActions(EventType type) { + if (events != null && events.containsKey(type)) + return events.get(type).getPreActions(); + return new LinkedList<>(); + } + + private List getPostActions(EventType type) { + if (events != null && events.containsKey(type)) + return events.get(type).getPostActions(); + return new LinkedList<>(); + } + + public void addEvent(RoleEvent event) { + this.events.put(event.getType(), event); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/RoleAssignment.java b/src/main/java/com/netgrif/application/engine/authorization/domain/RoleAssignment.java new file mode 100644 index 00000000000..4066922c6bf --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/RoleAssignment.java @@ -0,0 +1,27 @@ +package com.netgrif.application.engine.authorization.domain; + +import lombok.Data; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +@Data +@Document +public abstract class RoleAssignment { + @Id + protected ObjectId id; + @Indexed + protected String actorId; + @Indexed + protected String roleId; + protected String roleImportId; + + public RoleAssignment() { + this.id = new ObjectId(); + } + + public String getStringId() { + return this.id.toString(); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/Session.java b/src/main/java/com/netgrif/application/engine/authorization/domain/Session.java new file mode 100644 index 00000000000..aca111d2869 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/Session.java @@ -0,0 +1,36 @@ +package com.netgrif.application.engine.authorization.domain; + +import lombok.Data; + +import java.time.Duration; +import java.time.LocalDateTime; + +@Data +public class Session { + private LocalDateTime from; + private LocalDateTime to; + + /** + * todo javadoc + * */ + public static Session forever() { + return new Session(); + } + + /** + * todo javadoc + * */ + public static Session withDuration(Duration duration) { + LocalDateTime now = LocalDateTime.now(); + return new Session(now, now.plus(duration)); + } + + public Session() { + this(LocalDateTime.now(), null); + } + + public Session(LocalDateTime from, LocalDateTime to) { + this.from = from; + this.to = to; + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/User.java b/src/main/java/com/netgrif/application/engine/authorization/domain/User.java new file mode 100644 index 00000000000..2bbed6f95f9 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/User.java @@ -0,0 +1,53 @@ +package com.netgrif.application.engine.authorization.domain; + +import com.netgrif.application.engine.authorization.domain.constants.UserConstants; +import com.netgrif.application.engine.workflow.domain.Case; + +/** + * todo javadoc + * */ +public class User extends Actor { + + public User(Case userCase) { + super(userCase); + } + + @Override + protected CanInitializeOutcome canInitialize(Case userCase) { + return new CanInitializeOutcome("Provided user case is of different process", + userCase.getProcessIdentifier().equals(UserConstants.PROCESS_IDENTIFIER)); + } + + @Override + public String getName() { + return getFullName(); + } + + /** + * todo javadoc + * */ + public String getFullName() { + return String.join(" ", getFirstname(), getLastname()); + } + + /** + * todo javadoc + * */ + public String getEmail() { + return (String) getCase().getDataSet().get(UserConstants.EMAIL_FIELD_ID).getRawValue(); + } + + /** + * todo javadoc + * */ + public String getFirstname() { + return (String) getCase().getDataSet().get(UserConstants.FIRSTNAME_FIELD_ID).getRawValue(); + } + + /** + * todo javadoc + * */ + public String getLastname() { + return (String) getCase().getDataSet().get(UserConstants.LASTNAME_FIELD_ID).getRawValue(); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/constants/ActorConstants.java b/src/main/java/com/netgrif/application/engine/authorization/domain/constants/ActorConstants.java new file mode 100644 index 00000000000..20cb445a9af --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/constants/ActorConstants.java @@ -0,0 +1,5 @@ +package com.netgrif.application.engine.authorization.domain.constants; + +public class ActorConstants { + public static final String GROUPS_FIELD_ID = "groupIds"; +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/constants/GroupConstants.java b/src/main/java/com/netgrif/application/engine/authorization/domain/constants/GroupConstants.java new file mode 100644 index 00000000000..d54fbd2ce99 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/constants/GroupConstants.java @@ -0,0 +1,11 @@ +package com.netgrif.application.engine.authorization.domain.constants; + +public class GroupConstants { + public static final String DEFAULT_GROUP_NAME = "default"; + + public static final String PROCESS_IDENTIFIER = "group"; + public static final String FILE_PATH = "engine-processes/group.xml"; + public static final String NAME_FIELD_ID = "name"; + public static final String MEMBERS_FIELD_ID = "memberIds"; + public static final String PARENT_GROUP_FIELD_ID = "parentGroupId"; +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/constants/UserConstants.java b/src/main/java/com/netgrif/application/engine/authorization/domain/constants/UserConstants.java new file mode 100644 index 00000000000..7735d566bf5 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/constants/UserConstants.java @@ -0,0 +1,9 @@ +package com.netgrif.application.engine.authorization.domain.constants; + +public class UserConstants { + public static final String PROCESS_IDENTIFIER = "user"; + public static final String FILE_PATH = "engine-processes/user.xml"; + public static final String EMAIL_FIELD_ID = "email"; + public static final String FIRSTNAME_FIELD_ID = "firstname"; + public static final String LASTNAME_FIELD_ID = "lastname"; +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/params/ActorParams.java b/src/main/java/com/netgrif/application/engine/authorization/domain/params/ActorParams.java new file mode 100644 index 00000000000..cdd8274ae5f --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/params/ActorParams.java @@ -0,0 +1,39 @@ +package com.netgrif.application.engine.authorization.domain.params; + +import com.netgrif.application.engine.authorization.domain.constants.ActorConstants; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.workflow.domain.CaseParams; +import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotNull; +import java.util.Map; + +@Getter +@Setter +public abstract class ActorParams extends CaseParams { + + protected CaseField groupIds; + + protected ActorParams(CaseField groupIds, Map properties) { + super(properties); + this.groupIds = groupIds; + } + + /** + * todo javadoc + * */ + protected DataSet toDataSetInternal(@NotNull DataSet dataSet) { + return dataSet; + } + + @Override + public DataSet toDataSet() { + DataSet dataSet = new DataSet(); + + dataSet.put(ActorConstants.GROUPS_FIELD_ID, this.groupIds); + + return toDataSetInternal(dataSet); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/params/GroupParams.java b/src/main/java/com/netgrif/application/engine/authorization/domain/params/GroupParams.java new file mode 100644 index 00000000000..fe58523544c --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/params/GroupParams.java @@ -0,0 +1,40 @@ +package com.netgrif.application.engine.authorization.domain.params; + +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotNull; +import java.util.Map; + +@Getter +public class GroupParams extends ActorParams { + protected TextField name; + @Setter + protected CaseField parentGroupId; + + @Builder(builderMethodName = "with") + private GroupParams(CaseField groupIds, Map properties, TextField name, CaseField parentGroupId) { + super(groupIds, properties); + this.name = name; + this.parentGroupId = parentGroupId; + } + + + @Override + protected DataSet toDataSetInternal(@NotNull DataSet dataSet) { + dataSet.put(GroupConstants.NAME_FIELD_ID, this.name); + dataSet.put(GroupConstants.PARENT_GROUP_FIELD_ID, this.parentGroupId); + + return dataSet; + } + + @Override + public String targetProcessIdentifier() { + return GroupConstants.PROCESS_IDENTIFIER; + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/params/UserParams.java b/src/main/java/com/netgrif/application/engine/authorization/domain/params/UserParams.java new file mode 100644 index 00000000000..4ab5320f7cf --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/params/UserParams.java @@ -0,0 +1,73 @@ +package com.netgrif.application.engine.authorization.domain.params; + +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authorization.domain.constants.UserConstants; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; +import lombok.Builder; +import lombok.Getter; + +import java.util.Map; + +@Getter +public class UserParams extends ActorParams { + protected TextField email; + protected TextField firstname; + protected TextField lastname; + + @Builder(builderMethodName = "with") + private UserParams(CaseField groupIds, Map properties, TextField email, TextField firstname, TextField lastname) { + super(groupIds, properties); + this.email = email; + this.firstname = firstname; + this.lastname = lastname; + } + + /** + * todo javadoc + * */ + public static UserParams fromIdentityParams(IdentityParams identityParams) { + TextField email = null, firstname = null, lastname = null; + + if (identityParams.getUsername() != null) { + email = new TextField(identityParams.getUsername().getRawValue()); + } + if (identityParams.getFirstname() != null) { + firstname = new TextField(identityParams.getFirstname().getRawValue()); + } + if (identityParams.getLastname() != null) { + lastname = new TextField(identityParams.getLastname().getRawValue()); + } + + return UserParams.with() + .email(email) + .firstname(firstname) + .lastname(lastname) + .build(); + } + + /** + * todo javadoc + * */ + public String getFullName() { + if (this.firstname == null || this.lastname == null) { + return ""; + } + return String.join(" ", this.firstname.getRawValue(), this.lastname.getRawValue()); + } + + @Override + protected DataSet toDataSetInternal(DataSet dataSet) { + dataSet.put(UserConstants.EMAIL_FIELD_ID, this.email); + dataSet.put(UserConstants.FIRSTNAME_FIELD_ID, this.firstname); + dataSet.put(UserConstants.LASTNAME_FIELD_ID, this.lastname); + + return dataSet; + } + + @Override + public String targetProcessIdentifier() { + return UserConstants.PROCESS_IDENTIFIER; + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/permissions/AccessPermissions.java b/src/main/java/com/netgrif/application/engine/authorization/domain/permissions/AccessPermissions.java new file mode 100644 index 00000000000..057a6d828a8 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/permissions/AccessPermissions.java @@ -0,0 +1,93 @@ +package com.netgrif.application.engine.authorization.domain.permissions; + +import lombok.Data; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; + +@Data +public class AccessPermissions { + + private Map> permissions; + + public AccessPermissions() { + this.permissions = new HashMap<>(); + } + + /** + * todo javadoc + * */ + public AccessPermissions(AccessPermissions accessPermissions) { + this(accessPermissions, new HashSet<>()); + } + + /** + * todo javadoc + * */ + public AccessPermissions(AccessPermissions accessPermissions, Set ignoreTypes) { + this(); + accessPermissions.forEach((roleId, permissionValues) -> { + Map clonedPermissionValues; + if (ignoreTypes.isEmpty()) { + clonedPermissionValues = new HashMap<>(permissionValues); + } else { + clonedPermissionValues = permissionValues.entrySet().stream() + .filter((permEntry) -> !ignoreTypes.contains(permEntry.getKey())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + this.addPermissions(roleId, clonedPermissionValues); + }); + } + + public void forEach(BiConsumer> action) { + this.permissions.forEach(action); + } + + public boolean containsKey(String roleId) { + return this.permissions.containsKey(roleId); + } + + public Map get(String roleId) { + return this.permissions.get(roleId); + } + + public void put(String roleId, Map permissions) { + this.permissions.put(roleId, permissions); + } + + public boolean isEmpty() { + return this.permissions.isEmpty(); + } + + /** + * todo javadoc + * */ + public void addPermission(String roleId, T permission, Boolean value) { + Map permissionEntry = new HashMap<>(); + permissionEntry.put(permission, value); + // permissionEntry must be mutable + this.addPermissions(roleId, permissionEntry); + } + + /** + * todo javadoc + * */ + public void addPermissions(String roleId, Map permissions) { + if (this.containsKey(roleId) && this.get(roleId) != null) { + this.get(roleId).putAll(permissions); + } else { + this.put(roleId, permissions); + } + } + + /** + * todo javadoc + * */ + public void addPermissions(AccessPermissions rolesAndPermissions) { + if (rolesAndPermissions == null) { + return; + } + rolesAndPermissions.forEach(this::addPermissions); + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/ProcessRolePermission.java b/src/main/java/com/netgrif/application/engine/authorization/domain/permissions/CasePermission.java similarity index 64% rename from src/main/java/com/netgrif/application/engine/petrinet/domain/roles/ProcessRolePermission.java rename to src/main/java/com/netgrif/application/engine/authorization/domain/permissions/CasePermission.java index fb76dff6b2c..adac83f53bc 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/ProcessRolePermission.java +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/permissions/CasePermission.java @@ -1,8 +1,8 @@ -package com.netgrif.application.engine.petrinet.domain.roles; +package com.netgrif.application.engine.authorization.domain.permissions; import com.fasterxml.jackson.annotation.JsonValue; -public enum ProcessRolePermission { +public enum CasePermission { CREATE, DELETE, VIEW; diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/permissions/TaskPermission.java b/src/main/java/com/netgrif/application/engine/authorization/domain/permissions/TaskPermission.java new file mode 100644 index 00000000000..af9f65bb962 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/permissions/TaskPermission.java @@ -0,0 +1,21 @@ +package com.netgrif.application.engine.authorization.domain.permissions; + + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum TaskPermission { + CANCEL, + ASSIGN, + FINISH, + VIEW, + REASSIGN, + /** + * A permission to view task, that is disabled + * */ + VIEW_DISABLED; + + @JsonValue + public String value() { + return super.name().toLowerCase(); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ApplicationRoleAssignmentRepository.java b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ApplicationRoleAssignmentRepository.java new file mode 100644 index 00000000000..ea931f14516 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ApplicationRoleAssignmentRepository.java @@ -0,0 +1,9 @@ +package com.netgrif.application.engine.authorization.domain.repositories; + +import com.netgrif.application.engine.authorization.domain.ApplicationRoleAssignment; + +import java.util.List; + +public interface ApplicationRoleAssignmentRepository { + List findAllByActor(String actorId); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ApplicationRoleAssignmentRepositoryImpl.java b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ApplicationRoleAssignmentRepositoryImpl.java new file mode 100644 index 00000000000..efa4d6db789 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ApplicationRoleAssignmentRepositoryImpl.java @@ -0,0 +1,31 @@ +package com.netgrif.application.engine.authorization.domain.repositories; + +import com.netgrif.application.engine.authorization.domain.ApplicationRoleAssignment; +import lombok.RequiredArgsConstructor; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.BasicQuery; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +@RequiredArgsConstructor +public class ApplicationRoleAssignmentRepositoryImpl implements ApplicationRoleAssignmentRepository { + + private final MongoTemplate mongoTemplate; + + @Override + public List findAllByActor(String actorId) { + return mongoTemplate.find(buildMatchQuery("actorId", actorId), ApplicationRoleAssignment.class); + } + + private Query buildMatchQuery(String field, Object value) { + return buildBasicQuery().addCriteria(Criteria.where(field).is(value)); + } + + private Query buildBasicQuery() { + return BasicQuery.query(Criteria.where("_class").is(ApplicationRoleAssignment.class.getName())); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ApplicationRoleRepository.java b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ApplicationRoleRepository.java new file mode 100644 index 00000000000..7ed44704786 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ApplicationRoleRepository.java @@ -0,0 +1,14 @@ +package com.netgrif.application.engine.authorization.domain.repositories; + +import com.netgrif.application.engine.authorization.domain.ApplicationRole; + +import java.util.List; + +public interface ApplicationRoleRepository { + + boolean existsByImportId(String importId); + + ApplicationRole findByImportId(String importId); + + List findAll(); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ApplicationRoleRepositoryImpl.java b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ApplicationRoleRepositoryImpl.java new file mode 100644 index 00000000000..5027233e8f8 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ApplicationRoleRepositoryImpl.java @@ -0,0 +1,48 @@ +package com.netgrif.application.engine.authorization.domain.repositories; + +import com.netgrif.application.engine.authorization.domain.ApplicationRole; +import lombok.RequiredArgsConstructor; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.BasicQuery; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.stereotype.Repository; + +import java.util.Collection; +import java.util.List; + +@Repository +@RequiredArgsConstructor +public class ApplicationRoleRepositoryImpl implements ApplicationRoleRepository { + + private final MongoTemplate mongoTemplate; + + @Override + public boolean existsByImportId(String importId) { + Query query = buildMatchQuery("importId", importId); + return mongoTemplate.exists(query, ApplicationRole.class); + } + + @Override + public ApplicationRole findByImportId(String importId) { + Query query = buildMatchQuery("importId", importId); + return mongoTemplate.findOne(query, ApplicationRole.class); + } + + @Override + public List findAll() { + return mongoTemplate.find(buildBasicQuery(), ApplicationRole.class); + } + + private Query buildInQuery(String field, Collection values) { + return buildBasicQuery().addCriteria(Criteria.where(field).in(values)); + } + + private Query buildMatchQuery(String field, Object value) { + return buildBasicQuery().addCriteria(Criteria.where(field).is(value)); + } + + private Query buildBasicQuery() { + return BasicQuery.query(Criteria.where("_class").is(ApplicationRole.class.getName())); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/CaseRoleAssignmentRepository.java b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/CaseRoleAssignmentRepository.java new file mode 100644 index 00000000000..897b0f2dd79 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/CaseRoleAssignmentRepository.java @@ -0,0 +1,11 @@ +package com.netgrif.application.engine.authorization.domain.repositories; + +import com.netgrif.application.engine.authorization.domain.CaseRoleAssignment; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; +import org.springframework.stereotype.Repository; + +@Repository +public interface CaseRoleAssignmentRepository extends MongoRepository, QuerydslPredicateExecutor { + Iterable removeAllByCaseId(String caseId); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/CaseRoleRepository.java b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/CaseRoleRepository.java new file mode 100644 index 00000000000..81901b44148 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/CaseRoleRepository.java @@ -0,0 +1,10 @@ +package com.netgrif.application.engine.authorization.domain.repositories; + +import com.netgrif.application.engine.authorization.domain.CaseRole; +import java.util.List; + +public interface CaseRoleRepository { + void removeAllByCaseId(String caseId); + List findAll(); + CaseRole findByCaseIdAndImportId(String caseId, String importId); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/CaseRoleRepositoryImpl.java b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/CaseRoleRepositoryImpl.java new file mode 100644 index 00000000000..8ca0aff60b5 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/CaseRoleRepositoryImpl.java @@ -0,0 +1,47 @@ +package com.netgrif.application.engine.authorization.domain.repositories; + +import com.netgrif.application.engine.authorization.domain.CaseRole; +import lombok.RequiredArgsConstructor; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.BasicQuery; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; + +@Repository +@RequiredArgsConstructor +public class CaseRoleRepositoryImpl implements CaseRoleRepository{ + + private final MongoTemplate mongoTemplate; + + @Override + public void removeAllByCaseId(String caseId) { + Query query = buildMatchQuery(Map.of("caseId", caseId)); + mongoTemplate.remove(query, CaseRole.class); + } + + @Override + public List findAll() { + return mongoTemplate.find(buildBasicQuery(), CaseRole.class); + } + + @Override + public CaseRole findByCaseIdAndImportId(String caseId, String importId) { + Query query = buildMatchQuery(Map.of("caseId", caseId, "importId", importId)); + return mongoTemplate.findOne(query, CaseRole.class); + } + + private Query buildMatchQuery(Map attributesAndValues) { + Query query = buildBasicQuery(); + attributesAndValues.forEach((attribute, value) -> + query.addCriteria(Criteria.where(attribute).is(value))); + return query; + } + + private Query buildBasicQuery() { + return BasicQuery.query(Criteria.where("_class").is(CaseRole.class.getName())); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ProcessRoleRepository.java b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ProcessRoleRepository.java new file mode 100755 index 00000000000..c4f2a7a0778 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ProcessRoleRepository.java @@ -0,0 +1,23 @@ +package com.netgrif.application.engine.authorization.domain.repositories; + +import com.netgrif.application.engine.authorization.domain.ProcessRole; + +import java.util.List; +import java.util.Set; + +public interface ProcessRoleRepository { + + List findAllByImportIdIn(Set importIds); + + List findAllByTitle_DefaultValue(String title); + + List findAllByImportId(String importId); + + boolean existsByImportId(String importId); + + ProcessRole findByImportId(String importId); + + List findAll(); + + long count(); +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ProcessRoleRepositoryImpl.java b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ProcessRoleRepositoryImpl.java new file mode 100644 index 00000000000..6d20acf10ac --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/ProcessRoleRepositoryImpl.java @@ -0,0 +1,72 @@ +package com.netgrif.application.engine.authorization.domain.repositories; + +import com.netgrif.application.engine.authorization.domain.ProcessRole; +import lombok.RequiredArgsConstructor; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.BasicQuery; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.stereotype.Repository; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +@Repository +@RequiredArgsConstructor +public class ProcessRoleRepositoryImpl implements ProcessRoleRepository { + + private final MongoTemplate mongoTemplate; + + @Override + public List findAllByImportIdIn(Set importIds) { + Query query = buildInQuery("importId", importIds); + return mongoTemplate.find(query, ProcessRole.class); + } + + @Override + public List findAllByTitle_DefaultValue(String title) { + Query query = buildMatchQuery("title.defaultValue", title); + return mongoTemplate.find(query, ProcessRole.class); + } + + @Override + public List findAllByImportId(String importId) { + Query query = buildMatchQuery("importId", importId); + return mongoTemplate.find(query, ProcessRole.class); + } + + @Override + public boolean existsByImportId(String importId) { + Query query = buildMatchQuery("importId", importId); + return mongoTemplate.exists(query, ProcessRole.class); + } + + @Override + public ProcessRole findByImportId(String importId) { + Query query = buildMatchQuery("importId", importId); + return mongoTemplate.findOne(query, ProcessRole.class); + } + + @Override + public List findAll() { + return mongoTemplate.find(buildBasicQuery(), ProcessRole.class); + } + + @Override + public long count() { + return mongoTemplate.count(buildBasicQuery(), ProcessRole.class); + } + + private Query buildInQuery(String field, Collection values) { + return buildBasicQuery().addCriteria(Criteria.where(field).in(values)); + } + + private Query buildMatchQuery(String field, Object value) { + return buildBasicQuery().addCriteria(Criteria.where(field).is(value)); + } + + private Query buildBasicQuery() { + return BasicQuery.query(Criteria.where("_class").is(ProcessRole.class.getName())); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/RoleAssignmentRepository.java b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/RoleAssignmentRepository.java new file mode 100644 index 00000000000..44b8ff476a9 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/RoleAssignmentRepository.java @@ -0,0 +1,22 @@ +package com.netgrif.application.engine.authorization.domain.repositories; + +import com.netgrif.application.engine.authorization.domain.RoleAssignment; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; +import org.springframework.stereotype.Repository; + +import java.util.Set; + +@Repository +public interface RoleAssignmentRepository extends MongoRepository, QuerydslPredicateExecutor { + Iterable findAllByActorIdAndRoleIdIn(String actorId, Set roleIds); + Iterable findAllByRoleIdIn(Set roleIds); + Iterable findAllByActorId(String actorId); + boolean existsByActorIdAndRoleId(String actorId, String roleId); + + Iterable removeAllByActorIdAndRoleIdIn(String actorId, Set roleIds); + RoleAssignment removeByActorIdAndRoleId(String actorId, String roleId); + Iterable removeAllByActorId(String actorId); + Iterable removeAllByRoleId(String roleId); + Iterable removeAllByRoleIdIn(Set roleIds); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/RoleRepository.java b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/RoleRepository.java new file mode 100644 index 00000000000..4a45a0a11b9 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/repositories/RoleRepository.java @@ -0,0 +1,10 @@ +package com.netgrif.application.engine.authorization.domain.repositories; + +import com.netgrif.application.engine.authorization.domain.Role; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; +import org.springframework.stereotype.Repository; + +@Repository +public interface RoleRepository extends MongoRepository, QuerydslPredicateExecutor { +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/LogicNotApplicableException.java b/src/main/java/com/netgrif/application/engine/authorization/domain/throwable/LogicNotApplicableException.java similarity index 71% rename from src/main/java/com/netgrif/application/engine/petrinet/domain/roles/LogicNotApplicableException.java rename to src/main/java/com/netgrif/application/engine/authorization/domain/throwable/LogicNotApplicableException.java index 5601820cd3f..523f5008bc0 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/LogicNotApplicableException.java +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/throwable/LogicNotApplicableException.java @@ -1,4 +1,4 @@ -package com.netgrif.application.engine.petrinet.domain.roles; +package com.netgrif.application.engine.authorization.domain.throwable; public class LogicNotApplicableException extends RuntimeException { public LogicNotApplicableException(Exception e) { diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/throwable/NotAllRolesAssignedException.java b/src/main/java/com/netgrif/application/engine/authorization/domain/throwable/NotAllRolesAssignedException.java new file mode 100644 index 00000000000..849b42dc90f --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/throwable/NotAllRolesAssignedException.java @@ -0,0 +1,8 @@ +package com.netgrif.application.engine.authorization.domain.throwable; + +public class NotAllRolesAssignedException extends RuntimeException { + + public NotAllRolesAssignedException(int numberOfRolesNotAssigned) { + super(String.format("%d roles were not assigned", numberOfRolesNotAssigned)); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/domain/throwable/NotAllRolesRemovedException.java b/src/main/java/com/netgrif/application/engine/authorization/domain/throwable/NotAllRolesRemovedException.java new file mode 100644 index 00000000000..46f1d5897ed --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/domain/throwable/NotAllRolesRemovedException.java @@ -0,0 +1,8 @@ +package com.netgrif.application.engine.authorization.domain.throwable; + +public class NotAllRolesRemovedException extends RuntimeException { + + public NotAllRolesRemovedException(int numberOfRolesNotAssigned) { + super(String.format("%d role assignments were not removed", numberOfRolesNotAssigned)); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/ActorService.java b/src/main/java/com/netgrif/application/engine/authorization/service/ActorService.java new file mode 100644 index 00000000000..bafeb88dfc3 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/ActorService.java @@ -0,0 +1,111 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.authorization.domain.Actor; +import com.netgrif.application.engine.authorization.domain.params.ActorParams; +import com.netgrif.application.engine.authorization.service.interfaces.IActorService; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseSearchService; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.workflow.service.CrudSystemCaseService; +import com.netgrif.application.engine.workflow.service.SystemCaseFactoryRegistry; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.mongodb.MongoTransactionManager; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +@Slf4j +public abstract class ActorService extends CrudSystemCaseService implements IActorService { + + public ActorService(ISessionManagerService sessionManagerService, IDataService dataService, + IWorkflowService workflowService, SystemCaseFactoryRegistry systemCaseFactory, + IElasticCaseSearchService elasticCaseSearchService, MongoTransactionManager mongoTransactionManager) { + super(sessionManagerService, dataService, workflowService, systemCaseFactory, elasticCaseSearchService, mongoTransactionManager); + } + + @Override + public T addGroup(T actor, String groupId) { + if (groupId == null) { + throw new IllegalArgumentException("Group is not provided"); + } + return addGroups(actor, Set.of(groupId)); + } + + @Override + public T addGroups(T actor, Set groupIdsToAdd) { + if (actor == null) { + throw new IllegalArgumentException("Provided actor is null"); + } + if (groupIdsToAdd == null) { + throw new IllegalArgumentException("Groups are not provided"); + } + + groupIdsToAdd = groupIdsToAdd.stream().filter(Objects::nonNull).collect(Collectors.toSet()); + if (groupIdsToAdd.isEmpty()) { + return actor; + } + + Set groupIds; + if (actor.getGroupIds() != null) { + groupIds = new HashSet<>(actor.getGroupIds()); + groupIds.addAll(groupIdsToAdd); + } else { + groupIds = new HashSet<>(groupIdsToAdd); + } + + final String activeActorId = sessionManagerService.getActiveActorId(); + return doUpdate(actor, new ActorGroupParams(CaseField.withValue(new ArrayList<>(groupIds))), activeActorId); + } + + @Override + public T removeGroup(T actor, String groupId) { + if (groupId == null) { + throw new IllegalArgumentException("Group is not provided"); + } + return removeGroups(actor, Set.of(groupId)); + } + + @Override + public T removeGroups(T actor, Set groupIdsToRemove) { + if (actor == null) { + throw new IllegalArgumentException("Provided actor is null"); + } + if (actor.getGroupIds() == null) { + return actor; + } + if (groupIdsToRemove == null) { + throw new IllegalArgumentException("Groups are not provided"); + } + groupIdsToRemove = groupIdsToRemove.stream().filter(Objects::nonNull).collect(Collectors.toSet()); + if (groupIdsToRemove.isEmpty()) { + return actor; + } + + List groupIds = new ArrayList<>(actor.getGroupIds()); + boolean isAnyRemoved = groupIds.removeAll(groupIdsToRemove); + + if (!isAnyRemoved) { + return actor; + } + + final String activeActorId = sessionManagerService.getActiveActorId(); + return doUpdate(actor, new ActorGroupParams(CaseField.withValue(groupIds)), activeActorId); + } + + /** + * todo javadoc + * */ + protected static class ActorGroupParams extends ActorParams { + protected ActorGroupParams(CaseField groupIds) { + super(groupIds, null); + } + + @Override + public String targetProcessIdentifier() { + return ""; + } + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/ActorTypeRegistry.java b/src/main/java/com/netgrif/application/engine/authorization/service/ActorTypeRegistry.java new file mode 100644 index 00000000000..adf85f375ff --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/ActorTypeRegistry.java @@ -0,0 +1,38 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.authorization.domain.Actor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +@Slf4j +@Service +public class ActorTypeRegistry { + + /** + * Key is a process identifier and value is a factory + * */ + private final Map> types; + + public ActorTypeRegistry() { + this.types = new ConcurrentHashMap<>(); + } + + public Set getRegisteredProcessIdentifiers() { + return this.types.keySet(); + } + + + // todo javadoc + public void registerActorType(String processIdentifier, Class implementationClass) { + if (!implementationClass.getSuperclass().equals(Actor.class)) { + log.warn("Cannot register [{}] as actor type, since it's not actor type.", processIdentifier); + return; + } + this.types.put(processIdentifier, implementationClass); + log.info("Registered [{}] as actor type", processIdentifier); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/AllActorService.java b/src/main/java/com/netgrif/application/engine/authorization/service/AllActorService.java new file mode 100644 index 00000000000..a9132e7b7da --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/AllActorService.java @@ -0,0 +1,55 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.authorization.domain.Actor; +import com.netgrif.application.engine.authorization.service.interfaces.IAllActorService; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.QCase; +import com.netgrif.application.engine.workflow.service.SystemCaseFactoryRegistry; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +@Slf4j +@Service +public class AllActorService implements IAllActorService { + + private final IWorkflowService workflowService; + private final SystemCaseFactoryRegistry factoryRegistry; + private final ActorTypeRegistry actorTypeRegistry; + + public AllActorService(IWorkflowService workflowService, SystemCaseFactoryRegistry factoryRegistry, + ActorTypeRegistry actorTypeRegistry) { + this.workflowService = workflowService; + this.factoryRegistry = factoryRegistry; + this.actorTypeRegistry = actorTypeRegistry; + } + + /** + * todo javadoc + * */ + @Override + public Optional findById(String caseId) { + // todo: release/8.0.0 for example for identity case, it returns optional, that is present. Is it an issue? + if (caseId == null) { + return Optional.empty(); + } + try { + Actor actor = (Actor) factoryRegistry.fromCase(workflowService.findOne(caseId)); + return Optional.ofNullable(actor); + } catch (IllegalArgumentException ignored) { + return Optional.empty(); + } + } + + @Override + public List findAll() { + List cases = workflowService.search(QCase.case$.processIdentifier.in(actorTypeRegistry.getRegisteredProcessIdentifiers()), + Pageable.unpaged()).getContent(); + return cases.stream().map(useCase -> (Actor) factoryRegistry.fromCase(useCase)).collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/ApplicationAuthorizationService.java b/src/main/java/com/netgrif/application/engine/authorization/service/ApplicationAuthorizationService.java new file mode 100644 index 00000000000..960254f8312 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/ApplicationAuthorizationService.java @@ -0,0 +1,45 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authorization.domain.ApplicationRole; +import com.netgrif.application.engine.authorization.service.interfaces.IApplicationAuthorizationService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleAssignmentService; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; +import org.springframework.stereotype.Service; + +import java.util.Set; + +@Service +public class ApplicationAuthorizationService extends AuthorizationService implements IApplicationAuthorizationService { + + + public ApplicationAuthorizationService(ISessionManagerService sessionManagerService, IRoleAssignmentService roleAssignmentService, + ApplicationRoleRunner applicationRoleRunner) { + super(sessionManagerService, applicationRoleRunner, roleAssignmentService); + } + + /** + * todo javadoc + * */ + @Override + public boolean hasApplicationRole(String roleName) { + if (roleName == null) { + return false; + } + + LoggedIdentity loggedIdentity = sessionManagerService.getLoggedIdentity(); + if (loggedIdentity == null || loggedIdentity.getActiveActorId() == null) { + return false; + } + + ApplicationRole appRole = applicationRoleRunner.getAppRole(roleName); + if (appRole == null) { + return false; + } + + Set roleIds = roleAssignmentService.findAllRoleIdsByActorAndGroups(loggedIdentity.getActiveActorId()); + + return roleIds.contains(appRole.getStringId()); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/AuthorizationService.java b/src/main/java/com/netgrif/application/engine/authorization/service/AuthorizationService.java new file mode 100644 index 00000000000..a84f5abf695 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/AuthorizationService.java @@ -0,0 +1,119 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authorization.domain.ApplicationRole; +import com.netgrif.application.engine.authorization.domain.permissions.AccessPermissions; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleAssignmentService; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; +import lombok.RequiredArgsConstructor; + +import java.util.*; + +@RequiredArgsConstructor +public abstract class AuthorizationService { + + protected final ISessionManagerService sessionManagerService; + protected final ApplicationRoleRunner applicationRoleRunner; + protected final IRoleAssignmentService roleAssignmentService; + + /** + * todo javadoc + * popisat vzorec (tak ako v elastic view permission service) + * */ + protected boolean canCallEvent(AccessPermissions processRolePermissions, + AccessPermissions caseRolePermissions, T permission) { + LoggedIdentity loggedIdentity = sessionManagerService.getLoggedIdentity(); + if (loggedIdentity == null || loggedIdentity.getActiveActorId() == null) { + return false; + } + + Set roleIds = roleAssignmentService.findAllRoleIdsByActorAndGroups(loggedIdentity.getActiveActorId()); + + if (isAdmin(roleIds)) { + return true; + } + + Optional permittedByCaseRoleOpt = isPermitted(roleIds, caseRolePermissions, permission); + if (permittedByCaseRoleOpt.isPresent()) { + return permittedByCaseRoleOpt.get(); + } + + Optional permittedByProcessRoleOpt = isPermitted(roleIds, processRolePermissions, permission); + + return permittedByProcessRoleOpt.orElse(false); + } + + protected boolean isAdmin() { + LoggedIdentity loggedIdentity = sessionManagerService.getLoggedIdentity(); + if (loggedIdentity == null || loggedIdentity.getActiveActorId() == null) { + return false; + } + return isAdmin(roleAssignmentService.findAllRoleIdsByActorAndGroups(loggedIdentity.getActiveActorId())); + } + + private boolean isAdmin(Set roleIds) { + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + return roleIds.contains(adminAppRole.getStringId()); + } + + /** + * Finds permission value by provided permissions and role ids + * + * @param roleIds role ids assigned to some actor + * @param resourcePermissions permission collection of some resource + * @param permission permission type to search for + * + * @return Optional boolean value, which is: + *
    + *
  1. Empty optional: if the permission value was not found by provided role ids
  2. + *
  3. Optional of true: if the positive permission was found by provided role ids (there must be no negative permission found)
  4. + *
  5. Optional of false: if the negative permission was found by provided role ids
  6. + *
+ * */ + private Optional isPermitted(Set roleIds, AccessPermissions resourcePermissions, T permission) { + // private on purpose + Optional isPermittedOpt = Optional.empty(); + + if (resourcePermissions.isEmpty()) { + return isPermittedOpt; + } + + for (Map.Entry> entry : resourcePermissions.getPermissions().entrySet()) { + if (!roleIds.contains(entry.getKey())) { + continue; + } + Map permissions = entry.getValue(); + isPermittedOpt = resolveNextPermissionValue(isPermittedOpt.orElse(null), permissions.get(permission)); + if (isPermittedOpt.isPresent() && !isPermittedOpt.get()) { + // permission is prohibited, no need of continuing + return isPermittedOpt; + } + } + + return isPermittedOpt; + } + + /** + * Resolves next permission value between previous iteration result and current iteration result + * + * @param previousPermissionValue isPermitted value of previous iteration of for loop in {@link #isPermitted} + * @param currentPermissionValue isPermitted value of current iteration of for loop in {@link #isPermitted} + * + * @return Optional isPermitted value. Scenarios: + *
    + *
  1. Empty optional: if the previous value was null (permission not found) and the current permission is also not found
  2. + *
  3. Optional of true: if the previous value was true or null, and the current value is true
  4. + *
  5. Optional of false: if the previous value was false, or the current value is false
  6. + *
+ * */ + private Optional resolveNextPermissionValue(Boolean previousPermissionValue, Boolean currentPermissionValue) { + if (previousPermissionValue == null) { + return Optional.ofNullable(currentPermissionValue); + } + if (previousPermissionValue && currentPermissionValue != null) { + return Optional.of(currentPermissionValue); + } + return Optional.of(previousPermissionValue); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/CaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/authorization/service/CaseAuthorizationService.java new file mode 100644 index 00000000000..fe674ebb6e3 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/CaseAuthorizationService.java @@ -0,0 +1,81 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.authorization.domain.permissions.AccessPermissions; +import com.netgrif.application.engine.authorization.domain.permissions.CasePermission; +import com.netgrif.application.engine.authorization.service.interfaces.*; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import com.netgrif.application.engine.petrinet.domain.Process; +import org.springframework.stereotype.Service; + +@Service +public class CaseAuthorizationService extends AuthorizationService implements ICaseAuthorizationService { + + private final IWorkflowService workflowService; + private final IPetriNetService processService; + + public CaseAuthorizationService(ISessionManagerService sessionManagerService, IRoleAssignmentService roleAssignmentService, + ApplicationRoleRunner applicationRoleRunner, IWorkflowService workflowService, + IPetriNetService processService) { + super(sessionManagerService, applicationRoleRunner, roleAssignmentService); + this.workflowService = workflowService; + this.processService = processService; + } + + /** + * Checks if the current actor has permission to create a case for a given process. + * @param processId identifier of the process to check create permissions for + * @return true if an actor has permission to create case, false otherwise + */ + @Override + public boolean canCallCreate(String processId) { + if (processId == null) { + return false; + } + try { + Process process = processService.getPetriNet(processId); + return canCallEvent(process.getProcessRolePermissions(), new AccessPermissions<>(), CasePermission.CREATE); + } catch(IllegalArgumentException ignore) { + return false; + } + } + + /** + * Checks if the current actor has permission to delete a specified case. + * @param caseId identifier of the case to check delete permissions for + * @return true if an actor has permission to delete case, false otherwise + */ + @Override + public boolean canCallDelete(String caseId) { + if (caseId == null) { + return false; + } + try { + Case targetCase = workflowService.findOne(caseId); + return canCallEvent(targetCase.getProcessRolePermissions(), targetCase.getCaseRolePermissions(), CasePermission.DELETE); + } catch(IllegalArgumentException ignore) { + return false; + } + } + + /** + * Checks if the current actor has permission to view a specified case. + * @param caseId identifier of the case to check view permissions for + * @return true if an actor has permission to view case, false otherwise + */ + @Override + public boolean canView(String caseId) { + if (caseId == null) { + return false; + } + try { + Case targetCase = workflowService.findOne(caseId); + return canCallEvent(targetCase.getProcessRolePermissions(), targetCase.getCaseRolePermissions(), CasePermission.VIEW); + } catch(IllegalArgumentException ignore) { + return false; + } + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/GroupService.java b/src/main/java/com/netgrif/application/engine/authorization/service/GroupService.java new file mode 100644 index 00000000000..066b2c20b00 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/GroupService.java @@ -0,0 +1,132 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.authorization.domain.Group; +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.authorization.domain.params.GroupParams; +import com.netgrif.application.engine.authorization.service.interfaces.IGroupService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseSearchService; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.startup.DefaultGroupRunner; +import com.netgrif.application.engine.workflow.domain.CaseParams; +import com.netgrif.application.engine.workflow.service.SystemCaseFactoryRegistry; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; +import org.springframework.data.mongodb.MongoTransactionManager; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; +import java.util.Set; + +@Slf4j +@Service +public class GroupService extends ActorService implements IGroupService { + + private final DefaultGroupRunner defaultGroupRunner; + private final IRoleService roleService; + + public GroupService(ISessionManagerService sessionManagerService, IDataService dataService, + IWorkflowService workflowService, SystemCaseFactoryRegistry systemCaseFactory, + IElasticCaseSearchService elasticCaseSearchService, @Lazy DefaultGroupRunner defaultGroupRunner, + IRoleService roleService, MongoTransactionManager mongoTransactionManager) { + super(sessionManagerService, dataService, workflowService, systemCaseFactory, elasticCaseSearchService, mongoTransactionManager); + this.defaultGroupRunner = defaultGroupRunner; + this.roleService = roleService; + } + + /** + * Searches for a group by its name + * + * @param name name of the group to find + * @return Optional containing the group if found, empty Optional if name is null or group not found + */ + @Override + public Optional findByName(String name) { + if (name == null) { + return Optional.empty(); + } + return findOneByQuery(fulltextFieldQuery(GroupConstants.NAME_FIELD_ID, name)); + } + + /** + * Checks whether a group with given name exists + * + * @param name name to check + * @return true if group exists, false if name is null or no such group exists + */ + @Override + public boolean existsByName(String name) { + if (name == null) { + return false; + } + return countByQuery(fulltextFieldQuery(GroupConstants.NAME_FIELD_ID, name)) > 0; + } + + /** + * Gets or creates the default group and ensures it has the default role + * + * @return default group instance, creates new one if it doesn't exist + */ + @Override + public Group getDefaultGroup() { + Group defaultGroup = defaultGroupRunner.getDefaultGroup(); + + if (defaultGroup == null) { + defaultGroup = doCreate(GroupParams.with() + .name(new TextField(GroupConstants.DEFAULT_GROUP_NAME)) + .build(), null); + log.info("Default group with id [{}] was created.", defaultGroup.getStringId()); + } + + roleService.assignRolesToActor(defaultGroup.getStringId(), Set.of(roleService.findDefaultRole().getStringId())); + + return defaultGroup; + } + + @Override + protected String getProcessIdentifier() { + return GroupConstants.PROCESS_IDENTIFIER; + } + + @Override + protected String isUniqueQuery(CaseParams params) { + GroupParams typedParams = (GroupParams) params; + return fulltextFieldQuery(GroupConstants.NAME_FIELD_ID, typedParams.getName().getRawValue()); + } + + @Override + protected void validateAndFixCreateParams(CaseParams params) throws IllegalArgumentException { + GroupParams typedParams = (GroupParams) params; + if (isTextFieldOrValueEmpty(typedParams.getName())) { + throw new IllegalArgumentException("Group must have a name"); + } + if (isForbidden(typedParams.getName().getRawValue())) { + throw new IllegalArgumentException(String.format("Group name [%s] is reserved by the system.", + typedParams.getName().getRawValue())); + } + + if (isCaseFieldOrValueEmpty(typedParams.getParentGroupId())) { + typedParams.setParentGroupId(CaseField.withValue(List.of(getDefaultGroup().getStringId()))); + } + } + + @Override + protected void validateAndFixUpdateParams(CaseParams params) throws IllegalArgumentException { + GroupParams typedParams = (GroupParams) params; + if (typedParams.getName() == null) { + return; + } + if (isTextFieldValueEmpty(typedParams.getName())) { + throw new IllegalArgumentException(); + } + if (isForbidden(typedParams.getName().getRawValue())) { + throw new IllegalArgumentException(String.format("Group name [%s] is reserved by the system.", + typedParams.getName().getRawValue())); + } + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/RoleAssignmentService.java b/src/main/java/com/netgrif/application/engine/authorization/service/RoleAssignmentService.java new file mode 100644 index 00000000000..8c579c7dbba --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/RoleAssignmentService.java @@ -0,0 +1,280 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.authorization.domain.*; +import com.netgrif.application.engine.authorization.domain.repositories.ApplicationRoleAssignmentRepository; +import com.netgrif.application.engine.authorization.domain.repositories.CaseRoleAssignmentRepository; +import com.netgrif.application.engine.authorization.domain.repositories.RoleAssignmentRepository; +import com.netgrif.application.engine.authorization.service.factory.RoleAssignmentFactory; +import com.netgrif.application.engine.authorization.service.interfaces.IAllActorService; +import com.netgrif.application.engine.authorization.service.interfaces.IGroupService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleAssignmentService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +@Slf4j +@Service +@RequiredArgsConstructor +public class RoleAssignmentService implements IRoleAssignmentService { + + private final RoleAssignmentRepository repository; + private final CaseRoleAssignmentRepository caseRoleAssignmentRepository; + private final ApplicationRoleAssignmentRepository applicationRoleAssignmentRepository; + private final ApplicationContext applicationContext; + private IAllActorService allActorService; + private IGroupService groupService; + + @Lazy + @Autowired + public void setAllActorService(IAllActorService allActorService) { + this.allActorService = allActorService; + } + + @Lazy + @Autowired + public void setGroupService(IGroupService groupService) { + this.groupService = groupService; + } + + /** + * todo javadoc + * */ + @Override + public List findAllByActorIdAndRoleIdIn(String actorId, Set roleIds) { + if (actorId == null || roleIds == null || roleIds.isEmpty()) { + return new ArrayList<>(); + } + return (List) repository.findAllByActorIdAndRoleIdIn(actorId, roleIds); + } + + /** + * Finds all role assignments for given set of role IDs + * @param roleIds Set of role IDs to find assignments for + * @return List of matching role assignments, empty list if no matches found or invalid input + */ + @Override + public List findAllByRoleIdIn(Set roleIds) { + if (roleIds == null || roleIds.isEmpty()) { + return new ArrayList<>(); + } + return (List) repository.findAllByRoleIdIn(roleIds); + } + + /** + * Finds all role assignments for given actor ID + * @param actorId ID of the actor to find assignments for + * @return List of all role assignments for the actor, empty list if no matches found or invalid input + */ + @Override + public List findAllByActorId(String actorId) { + if (actorId == null) { + return new ArrayList<>(); + } + return (List) repository.findAllByActorId(actorId); + } + + /** + * Finds all role IDs assigned to given actor + * @param actorId ID of the actor to find role IDs for + * @return Set of role IDs assigned to the actor, empty set if no matches found or invalid input + */ + @Override + public Set findAllRoleIdsByActorId(String actorId) { + if (actorId == null) { + return new HashSet<>(); + } + List result = (List) repository.findAllByActorId(actorId); + return result.stream().map(RoleAssignment::getRoleId).collect(Collectors.toSet()); + } + + @Override + public Set findAllRoleIdsByActorAndGroups(String actorId) { + if (actorId == null) { + return new HashSet<>(); + } + Optional actorOpt = allActorService.findById(actorId); + if (actorOpt.isEmpty()) { + throw new IllegalStateException(String.format("Actor with id [%s] doesn't exist.", actorId)); + } + + Set roleIds = findAllRoleIdsByActorId(actorId); + roleIds.addAll(findRoleIdsByGroups(actorOpt.get().getGroupIds())); + + return roleIds; + } + + /** + * Checks if a role assignment exists for given actor and role + * @param actorId ID of the actor to check + * @param roleId ID of the role to check + * @return true if assignment exists, false otherwise + */ + @Override + public boolean existsByActorAndRole(String actorId, String roleId) { + return repository.existsByActorIdAndRoleId(actorId, roleId); + } + + /** + * Finds all application role assignments for given actor + * @param actorId ID of the actor to find application assignments for + * @return List of application role assignments for the actor + */ + @Override + public List findApplicationAssignmentsByActor(String actorId) { + return applicationRoleAssignmentRepository.findAllByActor(actorId); + } + + /** + * Creates new role assignments for given actor and roles + * @param actorId ID of the actor to create assignments for + * @param roles List of roles to assign + * @return List of created role assignments, empty list if invalid input + */ + @Override + public List createAssignments(String actorId, List roles) { + if (actorId == null || roles == null || roles.isEmpty()) { + return new ArrayList<>(); + } + List assignments = doCreateAssignments(actorId, roles); + return repository.saveAll(assignments); + } + + /** + * Creates new role assignment for given actor and role + * @param actorId ID of the actor to create assignment for + * @param role Role to assign + * @return Created role assignment or null if creation failed + */ + @Override + public RoleAssignment createAssignment(String actorId, Role role) { + return createAssignments(actorId, List.of(role)).stream().findFirst().orElse(null); + } + + /** + * Removes multiple role assignments for given actor and role IDs + * @param actorId ID of the actor to remove assignments from + * @param roleIds Set of role IDs to remove + * @return List of removed role assignments, empty list if no matches found or invalid input + */ + @Override + public List removeAssignments(String actorId, Set roleIds) { + if (actorId == null || roleIds == null || roleIds.isEmpty()) { + return new ArrayList<>(); + } + return (List) repository.removeAllByActorIdAndRoleIdIn(actorId, roleIds); + } + + /** + * Removes single role assignment for given actor and role ID + * @param actorId ID of the actor to remove assignment from + * @param roleId ID of the role to remove + * @return Removed role assignment or null if not found or invalid input + */ + @Override + public RoleAssignment removeAssignment(String actorId, String roleId) { + if (actorId == null || roleId == null) { + return null; + } + return repository.removeByActorIdAndRoleId(actorId, roleId); + } + + /** + * Removes all role assignments for given actor + * @param actorId ID of the actor to remove assignments for + * @return List of removed role assignments, empty list if no matches found or invalid input + */ + @Override + public List removeAssignmentsByActor(String actorId) { + if (actorId == null) { + return new ArrayList<>(); + } + return (List) repository.removeAllByActorId(actorId); + } + + /** + * Removes all role assignments for given role + * @param roleId ID of the role to remove assignments for + * @return List of removed role assignments, empty list if no matches found or invalid input + */ + @Override + public List removeAssignmentsByRole(String roleId) { + if (roleId == null) { + return new ArrayList<>(); + } + return (List) repository.removeAllByRoleId(roleId); + } + + /** + * Removes all role assignments for given set of roles + * @param roleIds Set of role IDs to remove assignments for + * @return List of removed role assignments, empty list if no matches found or invalid input + */ + @Override + public List removeAssignmentsByRoles(Set roleIds) { + if (roleIds == null || roleIds.isEmpty()) { + return new ArrayList<>(); + } + return (List) repository.removeAllByRoleIdIn(roleIds); + } + + /** + * Removes all case role assignments for given case + * @param caseId ID of the case to remove assignments for + * @return List of removed case role assignments, empty list if no matches found or invalid input + */ + @Override + public List removeAssignmentsByCase(String caseId) { + if (caseId == null) { + return new ArrayList<>(); + } + return (List) caseRoleAssignmentRepository.removeAllByCaseId(caseId); + } + + private Set findRoleIdsByGroups(List groupIds) { + if (groupIds == null || groupIds.isEmpty()) { + return new HashSet<>(); + } + Set alreadyProcessedGroupIds = new HashSet<>(); + Set roleIds = new HashSet<>(); + for (String groupId : groupIds) { + roleIds.addAll(findRoleIdsByGroupRecursive(groupId, alreadyProcessedGroupIds)); + alreadyProcessedGroupIds.add(groupId); + } + return roleIds; + } + + private Set findRoleIdsByGroupRecursive(String groupId, Set alreadyProcessedGroupIds) { + if (alreadyProcessedGroupIds.contains(groupId)) { + return new HashSet<>(); + } + Optional groupOpt = groupService.findById(groupId); + if (groupOpt.isEmpty()) { + throw new IllegalStateException(String.format("Group with id [%s] doesn't exist.", groupId)); + } + + Set roleIds = findAllRoleIdsByActorId(groupId); + alreadyProcessedGroupIds.add(groupId); + if (groupOpt.get().getParentGroupId() != null) { + roleIds.addAll(findRoleIdsByGroupRecursive(groupOpt.get().getParentGroupId(), alreadyProcessedGroupIds)); + } + + return roleIds; + } + + private List doCreateAssignments(String actorId, List roles) { + return roles.stream().map(role -> { + RoleAssignmentFactory factory = getAssignmentFactoryBean(role); + return factory.createAssignment(role, actorId); + }).collect(Collectors.toList()); + } + + private RoleAssignmentFactory getAssignmentFactoryBean(Role role) { + return (RoleAssignmentFactory) applicationContext.getBean(role.getAssignmentFactoryClass()); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/RoleService.java b/src/main/java/com/netgrif/application/engine/authorization/service/RoleService.java new file mode 100644 index 00000000000..4abafd8b6c7 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/RoleService.java @@ -0,0 +1,505 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.authorization.domain.*; +import com.netgrif.application.engine.authorization.domain.permissions.AccessPermissions; +import com.netgrif.application.engine.authorization.domain.permissions.CasePermission; +import com.netgrif.application.engine.authorization.domain.permissions.TaskPermission; +import com.netgrif.application.engine.authorization.domain.repositories.ApplicationRoleRepository; +import com.netgrif.application.engine.authorization.domain.repositories.CaseRoleRepository; +import com.netgrif.application.engine.authorization.domain.repositories.ProcessRoleRepository; +import com.netgrif.application.engine.authorization.domain.repositories.RoleRepository; +import com.netgrif.application.engine.authorization.domain.throwable.NotAllRolesAssignedException; +import com.netgrif.application.engine.authorization.service.interfaces.IAllActorService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleAssignmentService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.event.events.authorization.ActorAssignRoleEvent; +import com.netgrif.application.engine.event.events.authorization.ActorRemoveRoleEvent; +import com.netgrif.application.engine.importer.model.EventPhaseType; +import com.netgrif.application.engine.importer.model.RoleEventType; +import com.netgrif.application.engine.petrinet.domain.I18nString; +import com.netgrif.application.engine.petrinet.domain.dataset.Field; +import com.netgrif.application.engine.petrinet.domain.dataset.FieldWithAllowedRoles; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionRunner; +import com.netgrif.application.engine.petrinet.domain.events.RoleEvent; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.Task; +import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +@Slf4j +@Service +@RequiredArgsConstructor +public class RoleService implements IRoleService { + + private final RoleRepository repository; + private final ProcessRoleRepository processRoleRepository; + private final ApplicationRoleRepository applicationRoleRepository; + private final CaseRoleRepository caseRoleRepository; + private final ActionRunner actionRunner; + private final ApplicationEventPublisher eventPublisher; + private IRoleAssignmentService roleAssignmentService; + private IAllActorService actorService; + private ITaskService taskService; + private IWorkflowService workflowService; + private ApplicationRoleRunner applicationRoleRunner; + + private ProcessRole defaultProcessRole; + private ProcessRole anonymousProcessRole; + + @Lazy + @Autowired + public void setTaskService(ITaskService taskService) { + this.taskService = taskService; + } + + @Lazy + @Autowired + public void setWorkflowService(IWorkflowService workflowService) { + this.workflowService = workflowService; + } + + @Lazy + @Autowired + public void setActorService(IAllActorService actorService) { + this.actorService = actorService; + } + + @Lazy + @Autowired + public void setRoleAssignmentService(IRoleAssignmentService roleAssignmentService) { + this.roleAssignmentService = roleAssignmentService; + } + + @Lazy + @Autowired + public void setApplicationRoleRunner(ApplicationRoleRunner applicationRoleRunner) { + this.applicationRoleRunner = applicationRoleRunner; + } + + /** + * todo javadoc + * */ + @Override + public List findAll() { + return repository.findAll(); + } + + /** + * todo javadoc + * */ + @Override + public List findAllById(Set roleIds) { + if (roleIds == null || roleIds.isEmpty()) { + return new ArrayList<>(); + } + return (List) repository.findAllById(roleIds); + } + + @Override + public Set findAllRoleIdsByActorAndGroups(String actorId) { + return roleAssignmentService.findAllRoleIdsByActorAndGroups(actorId); + } + + /** + * todo javadoc + * */ + @Override + public Role findDefaultRole() { + if (defaultProcessRole == null) { + Optional defaultOpt = findSystemRoleByImportId(ProcessRole.DEFAULT_ROLE); + if (defaultOpt.isPresent()) { + defaultProcessRole = defaultOpt.get(); + } else { + ProcessRole defaultRole = new ProcessRole(ProcessRole.DEFAULT_ROLE); + defaultRole.setTitle(new I18nString(ProcessRole.DEFAULT_ROLE)); + defaultRole.setDescription(new I18nString("Default system process role")); + defaultRole.setEvents(new LinkedHashMap<>()); + defaultProcessRole = (ProcessRole) save(defaultRole); + if (defaultProcessRole != null) { + log.info("Default process role created."); + } + } + } + return defaultProcessRole; + } + + /** + * todo javadoc + * */ + @Override + public Role findAnonymousRole() { + if (anonymousProcessRole == null) { + Optional anonymousOpt = findSystemRoleByImportId(ProcessRole.ANONYMOUS_ROLE); + if (anonymousOpt.isPresent()) { + anonymousProcessRole = anonymousOpt.get(); + } else { + ProcessRole anonymousRole = new ProcessRole(ProcessRole.ANONYMOUS_ROLE); + anonymousRole.setTitle(new I18nString(ProcessRole.ANONYMOUS_ROLE)); + anonymousRole.setDescription(new I18nString("Anonymous system process role")); + anonymousRole.setEvents(new LinkedHashMap<>()); + anonymousProcessRole = (ProcessRole) save(anonymousRole); + if (anonymousProcessRole != null) { + log.info("Anonymous process role created."); + } + } + } + return anonymousProcessRole; + } + + /** + * todo javadoc + * */ + @Override + public List findAllApplicationRoles() { + return applicationRoleRepository.findAll(); + } + + /** + * todo javadoc + * */ + @Override + public boolean existsApplicationRoleByImportId(String importId) { + return applicationRoleRepository.existsByImportId(importId); + } + + /** + * todo javadoc + * */ + @Override + public ApplicationRole findApplicationRoleByImportId(String importId) { + ApplicationRole appRole = applicationRoleRunner.getAppRole(importId); + if (appRole == null) { + return applicationRoleRepository.findByImportId(importId); + } + return appRole; + } + + /** + * todo javadoc + * */ + @Override + public List findAllProcessRoles() { + return processRoleRepository.findAll(); + } + + /** + * todo javadoc + * */ + @Override + public List findAllProcessRolesByImportIds(Set roleImportIds) { + if (roleImportIds == null || roleImportIds.isEmpty()) { + return new ArrayList<>(); + } + return processRoleRepository.findAllByImportIdIn(roleImportIds); + } + + /** + * todo javadoc + * */ + @Override + public List findProcessRolesByDefaultTitle(String title) { + return processRoleRepository.findAllByTitle_DefaultValue(title); + } + + /** + * todo javadoc + * */ + @Override + public boolean existsProcessRoleByImportId(String importId) { + return processRoleRepository.existsByImportId(importId); + } + + /** + * todo javadoc + * */ + @Override + public ProcessRole findProcessRoleByImportId(String importId) { + return processRoleRepository.findByImportId(importId); + } + + /** + * todo javadoc + * */ + @Override + public List findAllCaseRoles() { + return caseRoleRepository.findAll(); + } + + /** + * todo javadoc + * */ + @Override + public CaseRole findCaseRoleByCaseIdAndImportId(String caseId, String importId) { + if (caseId == null || importId == null) { + return null; + } + return caseRoleRepository.findByCaseIdAndImportId(caseId, importId); + } + + /** + * todo javadoc + * */ + @Override + public Role save(Role role) { + if (role == null) { + return null; + } + return repository.save(role); + } + + /** + * todo javadoc + * */ + @Override + public List saveAll(Collection roles) { + if (roles == null || roles.isEmpty()) { + return new ArrayList<>(); + } + return repository.saveAll(roles); + } + + /** + * todo javadoc + * */ + @Override + public void remove(Role role) { + if (role == null) { + return; + } + roleAssignmentService.removeAssignmentsByRole(role.getStringId()); + repository.delete(role); + } + + /** + * todo javadoc + * */ + @Override + public void removeAll(Collection roles) { + if (roles == null || roles.isEmpty()) { + return; + } + Set roleIds = roles.stream().map(Role::getStringId).collect(Collectors.toSet()); + roleAssignmentService.removeAssignmentsByRoles(roleIds); + repository.deleteAll(roles); + } + + /** + * todo javadoc + * */ + @Override + public void removeAllByCase(String caseId) { + roleAssignmentService.removeAssignmentsByCase(caseId); + caseRoleRepository.removeAllByCaseId(caseId); + } + + /** + * todo javadoc + * */ + @Override + public void resolveCaseRolesOnCase(Case useCase, AccessPermissions caseRolePermissions, + boolean saveUseCase) { + useCase.addCaseRolePermissions(createRolesAndBuildPermissions(useCase, caseRolePermissions, saveUseCase)); + } + + /** + * todo javadoc + * */ + @Override + public void resolveCaseRolesOnTask(Case useCase, Task task, AccessPermissions caseRolePermissions, + boolean saveUseCase, boolean saveTask) { + task.addCaseRolePermissions(createRolesAndBuildPermissions(useCase, caseRolePermissions, saveUseCase)); + if (!caseRolePermissions.isEmpty() && saveTask) { + taskService.save(task); + } + } + + /** + * todo javadoc + * */ + @Override + public List assignRolesToActor(String actorId, Set roleIds) { + return assignRolesToActor(actorId, roleIds, new HashMap<>()); + } + + /** + * todo javadoc + * */ + @Override + public List assignRolesToActor(String actorId, Set roleIds, Map params) { + Optional actorOpt = actorService.findById(actorId); + if (actorOpt.isEmpty()) { + throw new IllegalArgumentException(String.format("Actor with id [%s] does not exist.", actorId)); + } + + List roles = findAllById(roleIds); + if (roles.isEmpty() && !roleIds.isEmpty()) { + throw new IllegalArgumentException("No roles found."); + } + if (roles.size() != roleIds.size()) { + throw new IllegalArgumentException("Not all roles were found!"); + } + + roles = filterNotAssignedRoles(actorId, roles); + + runAllSuitableActionsOnRoles(roles, RoleEventType.ASSIGN, EventPhaseType.PRE, params); + List newRoleAssignments = roleAssignmentService.createAssignments(actorId, roles); + if (roles.size() > newRoleAssignments.size()) { + // todo: release/8.0.0 keep this exception? + throw new NotAllRolesAssignedException(roles.size() - newRoleAssignments.size()); + } + eventPublisher.publishEvent(new ActorAssignRoleEvent(actorOpt.get(), roles)); + runAllSuitableActionsOnRoles(roles, RoleEventType.ASSIGN, EventPhaseType.POST, params); + + return roles; + } + + /* + * todo javadoc + * */ + @Override + public List removeRolesFromActor(String actorId, Set roleIds) { + return removeRolesFromActor(actorId, roleIds, new HashMap<>()); + } + + /** + * todo javadoc + * */ + @Override + public List removeRolesFromActor(String actorId, Set roleIds, Map params) { + List roles = findAllById(roleIds); + if (roles.isEmpty() && !roleIds.isEmpty()) { + throw new IllegalArgumentException("No roles found."); + } + if (roles.size() != roleIds.size()) { + throw new IllegalArgumentException("Not all roles were found!"); + } + + roles = filterAssignedRoles(actorId, roles); + + runAllSuitableActionsOnRoles(roles, RoleEventType.REMOVE, EventPhaseType.PRE, params); + Set roleIdsToRemove = roles.stream().map(Role::getStringId).collect(Collectors.toSet()); + List removedAssignments = roleAssignmentService.removeAssignments(actorId, roleIdsToRemove); + if (roles.size() > removedAssignments.size()) { + throw new NotAllRolesAssignedException(roles.size() - removedAssignments.size()); + } + if (!removedAssignments.isEmpty()) { + Optional actorOpt = actorService.findById(actorId); + if (actorOpt.isPresent()) { + eventPublisher.publishEvent(new ActorRemoveRoleEvent(actorOpt.get(), roles)); + } else { + log.warn("Removed {} roles from non-existing actor with id [{}]", removedAssignments.size(), actorId); + } + } + runAllSuitableActionsOnRoles(roles, RoleEventType.REMOVE, EventPhaseType.POST, params); + + return roles; + } + + public void clearCache() { + this.defaultProcessRole = null; + this.anonymousProcessRole = null; + } + + private Optional findSystemRoleByImportId(String importId) { + List processRoles = processRoleRepository.findAllByImportId(importId); + if (processRoles.size() > 1) { + throw new IllegalStateException(String.format("More than 1 %s process role exists!", importId)); + } + return processRoles.stream().findFirst(); + } + + /** + * todo javadoc + * */ + private AccessPermissions createRolesAndBuildPermissions(Case useCase, AccessPermissions actorRefPermissions, + boolean saveUseCase) { + List rolesToSave = new ArrayList<>(); + AccessPermissions resultPermissions = new AccessPermissions<>(); + + actorRefPermissions.forEach((userListId, permissions) -> { + CaseRole caseRole = caseRoleRepository.findByCaseIdAndImportId(useCase.getStringId(), userListId); + if (caseRole == null) { + caseRole = new CaseRole(userListId, useCase.getStringId()); + } + Field userListField = useCase.getDataSet().getFields().get(userListId); + if (userListField != null) { + ((FieldWithAllowedRoles) userListField).getCaseRoleIds().add(caseRole.getStringId()); + } else { + throw new IllegalStateException(String.format("Case role [%s} in process [%s] references non existing dataField in case [%s]", + userListId, useCase.getPetriNetId(), useCase.getStringId())); + } + rolesToSave.add(caseRole); + resultPermissions.put(caseRole.getStringId(), new HashMap<>(permissions)); + }); + + if (!actorRefPermissions.isEmpty() && saveUseCase) { + workflowService.save(useCase); + } + saveAll(rolesToSave); + return resultPermissions; + } + + private List filterAssignedRoles(String actorId, List rolesToBeNotAssigned) { + return filterRoles(actorId, rolesToBeNotAssigned, true); + } + + private List filterNotAssignedRoles(String actorId, List rolesToBeNotAssigned) { + return filterRoles(actorId, rolesToBeNotAssigned, false); + } + + private List filterRoles(String actorId, List roles, boolean filterAssigned) { + Set roleIds = roles.stream().map(Role::getStringId).collect(Collectors.toSet()); + List assignments = roleAssignmentService.findAllByActorIdAndRoleIdIn(actorId, roleIds); + + if (!assignments.isEmpty()) { + Set assignedRoleIds = assignments.stream().map(RoleAssignment::getRoleId).collect(Collectors.toSet()); + return roles.stream().filter(role -> filterAssigned == assignedRoleIds.contains(role.getStringId())) + .collect(Collectors.toList()); + } + return roles; + } + + private void runAllSuitableActionsOnRoles(List roles, RoleEventType requiredEventType, + EventPhaseType requiredPhase, Map params) { + roles.forEach(role -> runAllSuitableActionsOnOneRole(role.getEvents(), requiredEventType, requiredPhase, params)); + } + + private void runAllSuitableActionsOnOneRole(Map eventMap, RoleEventType requiredEventType, EventPhaseType requiredPhase, Map params) { + if (eventMap == null) { + return; + } + eventMap.forEach((eventType, event) -> { + if (eventType != requiredEventType) { + return; + } + + runActionsBasedOnPhase(event, requiredPhase, params); + }); + } + + private void runActionsBasedOnPhase(RoleEvent event, EventPhaseType requiredPhase, Map params) { + switch (requiredPhase) { + case PRE: + runActions(event.getPreActions(), params); + break; + case POST: + runActions(event.getPostActions(), params); + break; + } + } + + private void runActions(List actions, Map params) { + actions.forEach(action -> actionRunner.run(action, null, params)); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/TaskAuthorizationService.java b/src/main/java/com/netgrif/application/engine/authorization/service/TaskAuthorizationService.java new file mode 100644 index 00000000000..dc5fe0783b2 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/TaskAuthorizationService.java @@ -0,0 +1,148 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authorization.domain.permissions.TaskPermission; +import com.netgrif.application.engine.authorization.service.interfaces.*; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; +import com.netgrif.application.engine.workflow.domain.State; +import com.netgrif.application.engine.workflow.domain.Task; +import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; +import org.springframework.stereotype.Service; + +@Service +public class TaskAuthorizationService extends AuthorizationService implements ITaskAuthorizationService { + + private final ITaskService taskService; + + public TaskAuthorizationService(ISessionManagerService sessionManagerService, IRoleAssignmentService roleAssignmentService, + ApplicationRoleRunner applicationRoleRunner, ITaskService taskService) { + super(sessionManagerService, applicationRoleRunner, roleAssignmentService); + this.taskService = taskService; + } + + /** + * todo javadoc + * */ + @Override + public boolean canCallAssign(String taskId) { + if (taskId == null) { + return false; + } + try { + Task task = taskService.findById(taskId); + return !taskService.isAssigned(task) + && canCallEvent(task.getProcessRolePermissions(), task.getCaseRolePermissions(), TaskPermission.ASSIGN); + } catch(IllegalArgumentException ignore) { + return false; + } + } + + /** + * todo javadoc + * */ + @Override + public boolean canCallCancel(String taskId) { + if (taskId == null) { + return false; + } + try { + Task task = taskService.findById(taskId); + return taskService.isAssigned(task) && isAssignee(task) + && canCallEvent(task.getProcessRolePermissions(), task.getCaseRolePermissions(), TaskPermission.CANCEL); + } catch(IllegalArgumentException ignore) { + return false; + } + } + + @Override + public boolean canCallReassign(String taskId) { + if (taskId == null) { + return false; + } + try { + Task task = taskService.findById(taskId); + return taskService.isAssigned(task) + && canCallEvent(task.getProcessRolePermissions(), task.getCaseRolePermissions(), TaskPermission.REASSIGN); + } catch(IllegalArgumentException ignore) { + return false; + } + } + + /** + * todo javadoc + * */ + @Override + public boolean canCallFinish(String taskId) { + if (taskId == null) { + return false; + } + try { + Task task = taskService.findById(taskId); + return taskService.isAssigned(task) && isAssignee(task) + && canCallEvent(task.getProcessRolePermissions(), task.getCaseRolePermissions(), TaskPermission.FINISH); + } catch(IllegalArgumentException ignore) { + return false; + } + } + + /** + * todo javadoc + * */ + @Override + public boolean canCallSetData(String taskId) { + return taskId != null && (isAssignee(taskId) || isAdmin()); + } + + /** + * todo javadoc + * */ + @Override + public boolean canCallGetData(String taskId) { + if (taskId == null) { + return false; + } + try { + return canCallGetData(taskService.findById(taskId)); + } catch(IllegalArgumentException ignore) { + return false; + } + } + + @Override + public boolean canCallGetData(Task task) { + if (task == null) { + return false; + } + + TaskPermission permission = task.getState().equals(State.ENABLED) ? TaskPermission.VIEW : TaskPermission.VIEW_DISABLED; + + return canCallEvent(task.getProcessRolePermissions(), task.getCaseRolePermissions(), permission); + } + + /** + * todo javadoc + * */ + @Override + public boolean canCallSaveFile(String taskId) { + return taskId != null && isAssignee(taskId); + } + + private boolean isAssignee(String taskId) { + LoggedIdentity loggedIdentity = sessionManagerService.getLoggedIdentity(); + if (loggedIdentity == null || loggedIdentity.getActiveActorId() == null) { + return false; + } + + return taskService.existsByTaskAndAssignee(taskId, loggedIdentity.getActiveActorId()); + } + + private boolean isAssignee(Task task) { + LoggedIdentity loggedIdentity = sessionManagerService.getLoggedIdentity(); + if (loggedIdentity == null || loggedIdentity.getActiveActorId() == null) { + return false; + } + + return task.getAssigneeId().equals(loggedIdentity.getActiveActorId()); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/UserService.java b/src/main/java/com/netgrif/application/engine/authorization/service/UserService.java new file mode 100644 index 00000000000..27a6689c969 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/UserService.java @@ -0,0 +1,117 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.authorization.domain.User; +import com.netgrif.application.engine.authorization.domain.constants.UserConstants; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.authorization.service.interfaces.IGroupService; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseSearchService; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.startup.SystemUserRunner; +import com.netgrif.application.engine.workflow.domain.CaseParams; +import com.netgrif.application.engine.workflow.service.SystemCaseFactoryRegistry; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; +import org.springframework.data.mongodb.MongoTransactionManager; +import org.springframework.stereotype.Service; + +import java.util.*; + +@Slf4j +@Service +public class UserService extends ActorService implements IUserService { + + private final IGroupService groupService; + private final SystemUserRunner systemUserRunner; + + public UserService(@Lazy IDataService dataService, ISessionManagerService sessionManagerService, + @Lazy IElasticCaseSearchService elasticCaseSearchService, @Lazy IWorkflowService workflowService, + SystemCaseFactoryRegistry systemCaseFactoryRegistry, IGroupService groupService, + SystemUserRunner systemUserRunner, MongoTransactionManager mongoTransactionManager) { + super(sessionManagerService, dataService, workflowService, systemCaseFactoryRegistry, elasticCaseSearchService, + mongoTransactionManager); + this.groupService = groupService; + this.systemUserRunner = systemUserRunner; + } + + /** + * Finds user by their email address + * @param email the email address to search for + * @return Optional containing User if found, empty Optional if email is null or user not found + */ + @Override + public Optional findByEmail(String email) { + if (email == null) { + return Optional.empty(); + } + return findOneByQuery(fulltextFieldQuery(UserConstants.EMAIL_FIELD_ID, email)); + } + + /** + * Checks whether user with given email exists + * @param email the email address to check + * @return true if user exists, false if email is null or user not found + */ + @Override + public boolean existsByEmail(String email) { + if (email == null) { + return false; + } + return countByQuery(fulltextFieldQuery(UserConstants.EMAIL_FIELD_ID, email)) > 0; + } + + /** + * Retrieves the system user account + * + * @return User representing the system user + */ + @Override + public User getSystemUser() { + return systemUserRunner.getSystemUser(); + } + + @Override + protected String getProcessIdentifier() { + return UserConstants.PROCESS_IDENTIFIER; + } + + @Override + protected String isUniqueQuery(CaseParams params) { + UserParams typedParams = (UserParams) params; + return fulltextFieldQuery(UserConstants.EMAIL_FIELD_ID, typedParams.getEmail().getRawValue()); + } + + @Override + protected void validateAndFixCreateParams(CaseParams params) throws IllegalArgumentException { + UserParams typedParams = (UserParams) params; + if (isTextFieldOrValueEmpty(typedParams.getEmail())) { + throw new IllegalArgumentException("User must have an email!"); + } + if (isForbidden(typedParams.getEmail().getRawValue())) { + throw new IllegalArgumentException(String.format("User email [%s] is reserved by the system.", + typedParams.getEmail().getRawValue())); + } + + if (isCaseFieldOrValueEmpty(typedParams.getGroupIds())) { + typedParams.setGroupIds(CaseField.withValue(List.of(groupService.getDefaultGroup().getStringId()))); + } + } + + @Override + protected void validateAndFixUpdateParams(CaseParams params) throws IllegalArgumentException { + UserParams typedParams = (UserParams) params; + if (typedParams.getEmail() == null) { + return; + } + if (isTextFieldValueEmpty(typedParams.getEmail())) { + throw new IllegalArgumentException("User must have an email!"); + } + if (isForbidden(typedParams.getEmail().getRawValue())) { + throw new IllegalArgumentException(String.format("User email [%s] is reserved by the system.", + typedParams.getEmail().getRawValue())); + } + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/factory/ApplicationRoleAssignmentFactory.java b/src/main/java/com/netgrif/application/engine/authorization/service/factory/ApplicationRoleAssignmentFactory.java new file mode 100644 index 00000000000..84f74082aef --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/factory/ApplicationRoleAssignmentFactory.java @@ -0,0 +1,19 @@ +package com.netgrif.application.engine.authorization.service.factory; + +import com.netgrif.application.engine.authorization.domain.ApplicationRole; +import com.netgrif.application.engine.authorization.domain.ApplicationRoleAssignment; +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.authorization.domain.RoleAssignment; +import org.springframework.stereotype.Service; + +@Service +public class ApplicationRoleAssignmentFactory extends RoleAssignmentFactory { + + @Override + protected RoleAssignment doCreateAssignment(Role role) { + ApplicationRole appRole = (ApplicationRole) role; + ApplicationRoleAssignment assignment = new ApplicationRoleAssignment(); + assignment.setApplicationId(appRole.getApplicationId()); + return assignment; + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/factory/CaseRoleAssignmentFactory.java b/src/main/java/com/netgrif/application/engine/authorization/service/factory/CaseRoleAssignmentFactory.java new file mode 100644 index 00000000000..a5ddced2859 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/factory/CaseRoleAssignmentFactory.java @@ -0,0 +1,19 @@ +package com.netgrif.application.engine.authorization.service.factory; + +import com.netgrif.application.engine.authorization.domain.CaseRole; +import com.netgrif.application.engine.authorization.domain.CaseRoleAssignment; +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.authorization.domain.RoleAssignment; +import org.springframework.stereotype.Service; + +@Service +public class CaseRoleAssignmentFactory extends RoleAssignmentFactory { + + @Override + protected RoleAssignment doCreateAssignment(Role role) { + CaseRole caseRole = (CaseRole) role; + CaseRoleAssignment assignment = new CaseRoleAssignment(); + assignment.setCaseId(caseRole.getCaseId()); + return assignment; + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/factory/ProcessRoleAssignmentFactory.java b/src/main/java/com/netgrif/application/engine/authorization/service/factory/ProcessRoleAssignmentFactory.java new file mode 100644 index 00000000000..339023e6ec9 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/factory/ProcessRoleAssignmentFactory.java @@ -0,0 +1,24 @@ +package com.netgrif.application.engine.authorization.service.factory; + +import com.netgrif.application.engine.authorization.domain.ProcessRoleAssignment; +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.authorization.domain.RoleAssignment; +import com.netgrif.application.engine.authorization.domain.Session; +import com.netgrif.application.engine.configuration.RBACProperties; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ProcessRoleAssignmentFactory extends RoleAssignmentFactory { + + private final RBACProperties properties; + + @Override + protected RoleAssignment doCreateAssignment(Role role) { + if (properties.getDefaultAssignmentSessionDuration() != null) { + return new ProcessRoleAssignment(Session.withDuration(properties.getDefaultAssignmentSessionDuration())); + } + return new ProcessRoleAssignment(); + } +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/factory/RoleAssignmentFactory.java b/src/main/java/com/netgrif/application/engine/authorization/service/factory/RoleAssignmentFactory.java new file mode 100644 index 00000000000..65383f699ff --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/factory/RoleAssignmentFactory.java @@ -0,0 +1,24 @@ +package com.netgrif.application.engine.authorization.service.factory; + +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.authorization.domain.RoleAssignment; + +public abstract class RoleAssignmentFactory { + + /** + * todo javadoc + * */ + protected abstract RoleAssignment doCreateAssignment(Role role); + + /** + * todo javadoc + * */ + public RoleAssignment createAssignment(Role role, String userId) { + RoleAssignment assignment = doCreateAssignment(role); + assignment.setRoleId(role.getStringId()); + assignment.setRoleImportId(role.getImportId()); + assignment.setActorId(userId); + return assignment; + } + +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IActorService.java b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IActorService.java new file mode 100644 index 00000000000..81271c462a8 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IActorService.java @@ -0,0 +1,13 @@ +package com.netgrif.application.engine.authorization.service.interfaces; + +import com.netgrif.application.engine.authorization.domain.Actor; +import com.netgrif.application.engine.workflow.service.interfaces.ICrudSystemCaseService; + +import java.util.Set; + +public interface IActorService extends ICrudSystemCaseService { + T addGroup(T actor, String groupId); + T addGroups(T actor, Set groupIdsToAdd); + T removeGroup(T actor, String groupId); + T removeGroups(T actor, Set groupIdsToRemove); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IAllActorService.java b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IAllActorService.java new file mode 100644 index 00000000000..c7ad549eb3a --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IAllActorService.java @@ -0,0 +1,11 @@ +package com.netgrif.application.engine.authorization.service.interfaces; + +import com.netgrif.application.engine.authorization.domain.Actor; + +import java.util.List; +import java.util.Optional; + +public interface IAllActorService { + Optional findById(String caseId); + List findAll(); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IApplicationAuthorizationService.java b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IApplicationAuthorizationService.java new file mode 100644 index 00000000000..f8ff2379003 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IApplicationAuthorizationService.java @@ -0,0 +1,5 @@ +package com.netgrif.application.engine.authorization.service.interfaces; + +public interface IApplicationAuthorizationService { + boolean hasApplicationRole(String roleName); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/ICaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/ICaseAuthorizationService.java new file mode 100644 index 00000000000..f8a787138ee --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/ICaseAuthorizationService.java @@ -0,0 +1,7 @@ +package com.netgrif.application.engine.authorization.service.interfaces; + +public interface ICaseAuthorizationService { + boolean canCallCreate(String processId); + boolean canCallDelete(String caseId); + boolean canView(String caseId); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IGroupService.java b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IGroupService.java new file mode 100644 index 00000000000..b0bb24e4662 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IGroupService.java @@ -0,0 +1,11 @@ +package com.netgrif.application.engine.authorization.service.interfaces; + +import com.netgrif.application.engine.authorization.domain.Group; + +import java.util.Optional; + +public interface IGroupService extends IActorService { + Optional findByName(String name); + boolean existsByName(String name); + Group getDefaultGroup(); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IRoleAssignmentService.java b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IRoleAssignmentService.java new file mode 100644 index 00000000000..430426033be --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IRoleAssignmentService.java @@ -0,0 +1,30 @@ +package com.netgrif.application.engine.authorization.service.interfaces; + +import com.netgrif.application.engine.authorization.domain.ApplicationRoleAssignment; +import com.netgrif.application.engine.authorization.domain.CaseRoleAssignment; +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.authorization.domain.RoleAssignment; + +import java.util.List; +import java.util.Set; + +public interface IRoleAssignmentService { + + List findAllByActorIdAndRoleIdIn(String actorId, Set roleIds); + List findAllByRoleIdIn(Set roleIds); + List findAllByActorId(String actorId); + Set findAllRoleIdsByActorId(String actorId); + Set findAllRoleIdsByActorAndGroups(String actorId); + boolean existsByActorAndRole(String actorId, String roleId); + + List findApplicationAssignmentsByActor(String actorId); + + List createAssignments(String actorId, List roles); + RoleAssignment createAssignment(String actorId, Role role); + List removeAssignments(String actorId, Set roleIds); + RoleAssignment removeAssignment(String actorId, String roleId); + List removeAssignmentsByActor(String actorId); + List removeAssignmentsByRole(String roleId); + List removeAssignmentsByRoles(Set roleIds); + List removeAssignmentsByCase(String caseId); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IRoleService.java b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IRoleService.java new file mode 100644 index 00000000000..7aa571ecafb --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IRoleService.java @@ -0,0 +1,52 @@ +package com.netgrif.application.engine.authorization.service.interfaces; + +import com.netgrif.application.engine.authorization.domain.ApplicationRole; +import com.netgrif.application.engine.authorization.domain.CaseRole; +import com.netgrif.application.engine.authorization.domain.ProcessRole; +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.authorization.domain.permissions.AccessPermissions; +import com.netgrif.application.engine.authorization.domain.permissions.CasePermission; +import com.netgrif.application.engine.authorization.domain.permissions.TaskPermission; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.Task; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public interface IRoleService { + List findAll(); + List findAllById(Set roleIds); + Set findAllRoleIdsByActorAndGroups(String actorId); + Role findDefaultRole(); + Role findAnonymousRole(); + + List findAllApplicationRoles(); + boolean existsApplicationRoleByImportId(String importId); + ApplicationRole findApplicationRoleByImportId(String importId); + + List findAllProcessRoles(); + List findAllProcessRolesByImportIds(Set roleImportIds); + List findProcessRolesByDefaultTitle(String title); + boolean existsProcessRoleByImportId(String importId); + ProcessRole findProcessRoleByImportId(String importId); + + List findAllCaseRoles(); + CaseRole findCaseRoleByCaseIdAndImportId(String caseId, String importId); + + Role save(Role role); + List saveAll(Collection roles); + void remove(Role role); + void removeAll(Collection roles); + void removeAllByCase(String caseId); + + void resolveCaseRolesOnCase(Case useCase, AccessPermissions caseRolePermissions, boolean saveUseCase); + void resolveCaseRolesOnTask(Case useCase, Task task, AccessPermissions caseRolePermissions, + boolean saveUseCase, boolean saveTask); + + List assignRolesToActor(String actorId, Set roleIds); + List assignRolesToActor(String actorId, Set roleIds, Map params); + List removeRolesFromActor(String actorId, Set roleIds); + List removeRolesFromActor(String actorId, Set roleIds, Map params); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/ITaskAuthorizationService.java b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/ITaskAuthorizationService.java new file mode 100644 index 00000000000..906188fec73 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/ITaskAuthorizationService.java @@ -0,0 +1,14 @@ +package com.netgrif.application.engine.authorization.service.interfaces; + +import com.netgrif.application.engine.workflow.domain.Task; + +public interface ITaskAuthorizationService { + boolean canCallAssign(String taskId); + boolean canCallCancel(String taskId); + boolean canCallReassign(String taskId); + boolean canCallFinish(String taskId); + boolean canCallSetData(String taskId); + boolean canCallGetData(String taskId); + boolean canCallGetData(Task task); + boolean canCallSaveFile(String taskId); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IUserService.java b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IUserService.java new file mode 100644 index 00000000000..400db5d784c --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/service/interfaces/IUserService.java @@ -0,0 +1,13 @@ +package com.netgrif.application.engine.authorization.service.interfaces; + +import com.netgrif.application.engine.authorization.domain.User; + +import java.util.List; +import java.util.Optional; + +public interface IUserService extends IActorService { + Optional findByEmail(String email); + boolean existsByEmail(String email); + List findAll(); + User getSystemUser(); +} diff --git a/src/main/java/com/netgrif/application/engine/authorization/web/RBACController.java b/src/main/java/com/netgrif/application/engine/authorization/web/RBACController.java new file mode 100644 index 00000000000..c33e07e3370 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/authorization/web/RBACController.java @@ -0,0 +1,114 @@ +package com.netgrif.application.engine.authorization.web; + +import com.netgrif.application.engine.authorization.domain.ApplicationRole; +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.hateoas.CollectionModel; +import org.springframework.hateoas.MediaTypes; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@Slf4j +@RestController +@RequiredArgsConstructor +@ConditionalOnProperty( + value = "nae.rbac.web.enabled", + havingValue = "true", + matchIfMissing = true +) +@RequestMapping("/api/authorization") +@Tag(name = "RBAC", description = "With this API you can manage roles and assignments") +public class RBACController { + private final IRoleService roleService; + + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") + @Operation(summary = "Assign roles to the actor", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) + @PostMapping(value = "/{actorId}/assign", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + }) + public CollectionModel assignRolesToActor(@PathVariable("actorId") String actorId, @RequestBody Set roleIds) { + try { + List assignedRoles = roleService.assignRolesToActor(actorId, roleIds); + Set assignedRoleIds = assignedRoles.stream().map(Role::getStringId).collect(Collectors.toSet()); + log.info("Roles [{}] assigned to actor [{}]", assignedRoleIds, actorId); + return CollectionModel.of(assignedRoles); + } catch (IllegalArgumentException e) { + log.error(e.getMessage(), e); + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, String.format("Roles weren't assigned: %s", e.getMessage())); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, + String.format("Something went wrong while assigning roles to actor [%s]", actorId)); + } + } + + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") + @Operation(summary = "Remove roles from the actor", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) + @PostMapping(value = "/{actorId}/remove", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + }) + public CollectionModel removeRolesFromActor(@PathVariable("actorId") String actorId, @RequestBody Set roleIds) { + try { + List removedRoles = roleService.removeRolesFromActor(actorId, roleIds); + Set removedRoleIds = removedRoles.stream().map(Role::getStringId).collect(Collectors.toSet()); + log.info("Roles [{}] removed from actor [{}]", removedRoleIds, actorId); + return CollectionModel.of(removedRoles); + } catch (IllegalArgumentException e) { + log.error(e.getMessage(), e); + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, String.format("Roles weren't removed: %s", e.getMessage())); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, + String.format("Something went wrong while removing roles from actor [%s]", actorId)); + } + } + + @Operation(summary = "Finds role ids assigned to provided actor", security = {@SecurityRequirement(name = "BasicAuth")}) + @GetMapping(value = "/{actorId}/roles", produces = MediaTypes.HAL_JSON_VALUE) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + }) + public Set findRoleIdsByActorAndGroups(@PathVariable("actorId") String actorId) { + try { + return roleService.findAllRoleIdsByActorAndGroups(actorId); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Something unexpected happened"); + } + } + + @Operation(summary = "Finds application role id by import id", security = {@SecurityRequirement(name = "BasicAuth")}) + @GetMapping(value = "/appRole/{importId}", produces = MediaTypes.HAL_JSON_VALUE) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + }) + public ApplicationRole findApplicationRole(@PathVariable("importId") String importId) { + try { + return roleService.findApplicationRoleByImportId(importId); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Something unexpected happened"); + } + } +} diff --git a/src/main/java/com/netgrif/application/engine/configuration/ElasticServiceConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/ElasticServiceConfiguration.java index 02404db0b1d..ae40bfe62b4 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/ElasticServiceConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/ElasticServiceConfiguration.java @@ -1,19 +1,17 @@ package com.netgrif.application.engine.configuration; import com.netgrif.application.engine.configuration.properties.ElasticsearchProperties; -import com.netgrif.application.engine.elastic.domain.ElasticCaseRepository; -import com.netgrif.application.engine.elastic.domain.ElasticTaskRepository; -import com.netgrif.application.engine.elastic.service.ElasticCaseService; -import com.netgrif.application.engine.elastic.service.ElasticTaskService; +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticCaseRepository; +import com.netgrif.application.engine.elastic.service.*; import com.netgrif.application.engine.elastic.service.executors.Executor; -import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; -import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; +import com.netgrif.application.engine.elastic.service.interfaces.*; +import com.netgrif.application.engine.elastic.service.query.ElasticPermissionQueryBuilder; +import com.netgrif.application.engine.elastic.service.query.ElasticTaskQueryBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; -import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; @Configuration @ConditionalOnProperty( @@ -27,13 +25,25 @@ public class ElasticServiceConfiguration { private ElasticCaseRepository caseRepository; @Autowired - private ElasticTaskRepository taskRepository; + private ElasticsearchProperties elasticsearchProperties; @Autowired - private ElasticsearchRestTemplate elasticsearchTemplate; + private IElasticCaseSearchService caseSearchService; @Autowired - private ElasticsearchProperties elasticsearchProperties; + private IElasticTaskSearchService taskSearchService; + + @Autowired + private ElasticPermissionQueryBuilder permissionQueryBuilder; + + @Autowired + private IElasticCaseMappingService caseMappingService; + + @Autowired + private ElasticTaskQueueManager elasticTaskQueueManager; + + @Autowired + private ElasticTaskQueryBuilder taskQueryBuilder; @Bean @Primary @@ -54,24 +64,25 @@ public Executor reindexingTaskTaskExecutor() { @Bean @Primary public IElasticCaseService elasticCaseService() { - return new ElasticCaseService(caseRepository, elasticsearchTemplate, executor()); + return new ElasticCaseService(caseRepository, executor(), caseMappingService, caseSearchService, permissionQueryBuilder); } @Bean @Primary public IElasticTaskService elasticTaskService() { - return new ElasticTaskService(elasticsearchTemplate); + return new ElasticTaskService(taskSearchService, elasticTaskQueueManager, taskQueryBuilder, permissionQueryBuilder); } @Bean public IElasticCaseService reindexingTaskElasticCaseService() { - return new ElasticCaseService(caseRepository, elasticsearchTemplate, reindexingTaskCaseExecutor()); + return new ElasticCaseService(caseRepository, reindexingTaskCaseExecutor(), caseMappingService, caseSearchService, + permissionQueryBuilder); } @Bean public IElasticTaskService reindexingTaskElasticTaskService() { - return new ElasticTaskService(elasticsearchTemplate); + return new ElasticTaskService(taskSearchService, elasticTaskQueueManager, taskQueryBuilder, permissionQueryBuilder); } } diff --git a/src/main/java/com/netgrif/application/engine/configuration/ElasticsearchConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/ElasticsearchConfiguration.java index dbd923e5a51..93fac3eb60c 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/ElasticsearchConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/ElasticsearchConfiguration.java @@ -1,7 +1,6 @@ package com.netgrif.application.engine.configuration; import com.netgrif.application.engine.configuration.properties.UriProperties; -import com.netgrif.application.engine.workflow.service.CaseEventHandler; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; @@ -74,9 +73,4 @@ public RestHighLevelClient client() { public ElasticsearchOperations elasticsearchTemplate() { return new ElasticsearchRestTemplate(client()); } - - @Bean - public CaseEventHandler caseEventHandler() { - return new CaseEventHandler(); - } } diff --git a/src/main/java/com/netgrif/application/engine/configuration/LayoutFlexConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/LayoutFlexConfiguration.java new file mode 100644 index 00000000000..24d0b36e47b --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/configuration/LayoutFlexConfiguration.java @@ -0,0 +1,18 @@ +package com.netgrif.application.engine.configuration; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.HashMap; +import java.util.Map; + +@Data +@Configuration +@ConfigurationProperties(prefix = "nae.layout.flex") +public class LayoutFlexConfiguration { + + private final Map root = new HashMap<>(); + private final Map container = new HashMap<>(); + private final Map children = new HashMap<>(); +} diff --git a/src/main/java/com/netgrif/application/engine/configuration/LayoutGridConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/LayoutGridConfiguration.java new file mode 100644 index 00000000000..f4e6c46910f --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/configuration/LayoutGridConfiguration.java @@ -0,0 +1,17 @@ +package com.netgrif.application.engine.configuration; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.HashMap; +import java.util.Map; + +@Data +@Configuration +@ConfigurationProperties(prefix = "nae.layout.grid") +public class LayoutGridConfiguration { + private final Map root = new HashMap<>(); + private final Map container = new HashMap<>(); + private final Map children = new HashMap<>(); +} diff --git a/src/main/java/com/netgrif/application/engine/configuration/LdapUserServiceConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/LdapUserServiceConfiguration.java index c9ebabf0849..56a12829fcb 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/LdapUserServiceConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/LdapUserServiceConfiguration.java @@ -1,7 +1,6 @@ package com.netgrif.application.engine.configuration; -import com.netgrif.application.engine.auth.service.LdapUserDetailsService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.authentication.service.LdapUserDetailsService; import com.netgrif.application.engine.ldap.service.LdapUserService; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.context.annotation.Bean; @@ -12,14 +11,15 @@ @ConditionalOnExpression("${nae.ldap.enabled:false}") public class LdapUserServiceConfiguration { - @Bean - public IUserService userService() { - return new LdapUserService(); - } +// @Bean +// public IUserService userService() { +// return new LdapUserService(); +// } @Bean public UserDetailsService userDetailsService() { - return new LdapUserDetailsService(); +// return new LdapUserDetailsService(); + return null; } } diff --git a/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java index 59bbdaa17fc..039407e4658 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java @@ -1,28 +1,22 @@ package com.netgrif.application.engine.configuration; -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.authentication.domain.PublicStrategy; import com.netgrif.application.engine.configuration.authentication.providers.NaeAuthProperties; import com.netgrif.application.engine.configuration.properties.NaeLdapProperties; import com.netgrif.application.engine.configuration.properties.SecurityConfigProperties; -import com.netgrif.application.engine.configuration.security.ImpersonationRequestFilter; -import com.netgrif.application.engine.configuration.security.PublicAuthenticationFilter; -import com.netgrif.application.engine.configuration.security.RestAuthenticationEntryPoint; -import com.netgrif.application.engine.configuration.security.SecurityContextFilter; +import com.netgrif.application.engine.configuration.security.*; +import com.netgrif.application.engine.configuration.security.factory.PublicAuthenticationFilterFactory; import com.netgrif.application.engine.configuration.security.filter.HostValidationRequestFilter; -import com.netgrif.application.engine.configuration.security.jwt.IJwtService; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService; import com.netgrif.application.engine.security.service.ISecurityContextService; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.core.env.Environment; import org.springframework.http.HttpStatus; -import org.springframework.security.authentication.AnonymousAuthenticationProvider; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @@ -37,7 +31,6 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.ForwardedHeaderFilter; -import java.util.HashSet; import java.util.List; import static org.springframework.http.HttpMethod.OPTIONS; @@ -47,40 +40,25 @@ @Controller @Configuration @EnableWebSecurity +@RequiredArgsConstructor @Order(SecurityProperties.DEFAULT_FILTER_ORDER) public class NaeSecurityConfiguration extends AbstractSecurityConfiguration { - @Autowired - private Environment env; + private final Environment env; - @Autowired - private RestAuthenticationEntryPoint authenticationEntryPoint; + private final RestAuthenticationEntryPoint authenticationEntryPoint; - @Autowired - private IAuthorityService authorityService; + private final ApplicationContext applicationContext; - @Autowired - private IJwtService jwtService; + private final NaeAuthProperties naeAuthProperties; - @Autowired - private IUserService userService; + private final SecurityConfigProperties properties; - @Autowired - private NaeAuthProperties naeAuthProperties; + private final PublicViewProperties publicProperties; - @Autowired - private SecurityConfigProperties properties; + private final ISecurityContextService securityContextService; - @Autowired - private ISecurityContextService securityContextService; - - @Autowired - protected NaeLdapProperties ldapProperties; - - @Autowired - protected IImpersonationService impersonationService; - - private static final String ANONYMOUS_USER = "anonymousUser"; + protected final NaeLdapProperties ldapProperties; @Bean public HttpSessionIdResolver httpSessionIdResolver() { @@ -119,7 +97,6 @@ protected void configure(HttpSecurity http) throws Exception { .addFilterBefore(new ForwardedHeaderFilter(), WebAsyncManagerIntegrationFilter.class) .addFilterBefore(createPublicAuthenticationFilter(), BasicAuthenticationFilter.class) .addFilterAfter(createSecurityContextFilter(), BasicAuthenticationFilter.class) - .addFilterAfter(impersonationRequestFilter(), BasicAuthenticationFilter.class) .addFilterAfter(hostValidationRequestFilter(), BasicAuthenticationFilter.class) .authorizeRequests() .antMatchers(getPatterns()).permitAll() @@ -178,17 +155,9 @@ protected SecurityConfigProperties getSecurityConfigProperties() { } protected PublicAuthenticationFilter createPublicAuthenticationFilter() throws Exception { - Authority authority = authorityService.getOrCreate(Authority.anonymous); - authority.setUsers(new HashSet<>()); - return new PublicAuthenticationFilter( - authenticationManager(), - new AnonymousAuthenticationProvider(ANONYMOUS_USER), - authority, - this.naeAuthProperties.getServerPatterns(), - this.naeAuthProperties.getAnonymousExceptions(), - this.jwtService, - this.userService - ); + PublicStrategy strategy = publicProperties.getStrategy(); + PublicAuthenticationFilterFactory filterFactory = (PublicAuthenticationFilterFactory) applicationContext.getBean(strategy.factoryClass); + return filterFactory.createFilter(authenticationManager()); } private SecurityContextFilter createSecurityContextFilter() { @@ -198,8 +167,4 @@ private SecurityContextFilter createSecurityContextFilter() { private HostValidationRequestFilter hostValidationRequestFilter() { return new HostValidationRequestFilter(properties); } - - private ImpersonationRequestFilter impersonationRequestFilter() { - return new ImpersonationRequestFilter(impersonationService); - } } diff --git a/src/main/java/com/netgrif/application/engine/configuration/PrototypesConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/PrototypesConfiguration.java index b23b385c5ac..171afbc5961 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/PrototypesConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/PrototypesConfiguration.java @@ -1,9 +1,9 @@ package com.netgrif.application.engine.configuration; -import com.netgrif.application.engine.auth.web.responsebodies.UserResourceAssembler; import com.netgrif.application.engine.importer.service.Importer; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionDelegate; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ExpressionDelegate; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ValidationDelegate; import com.netgrif.application.engine.workflow.domain.FileStorageConfiguration; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; @@ -31,15 +31,15 @@ public ExpressionDelegate expressionDelegate() { return new ExpressionDelegate(); } - @Bean("fileStorageConfiguration") + @Bean("validationDelegate") @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public FileStorageConfiguration fileStorageConfiguration() { - return new FileStorageConfiguration(); + public ValidationDelegate validationDelegate() { + return new ValidationDelegate(); } - @Bean("userResourceAssembler") + @Bean("fileStorageConfiguration") @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public UserResourceAssembler userResourceAssembler() { - return new UserResourceAssembler(); + public FileStorageConfiguration fileStorageConfiguration() { + return new FileStorageConfiguration(); } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/configuration/PublicViewProperties.java b/src/main/java/com/netgrif/application/engine/configuration/PublicViewProperties.java index 9f29cebb83a..77fd2b54f06 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/PublicViewProperties.java +++ b/src/main/java/com/netgrif/application/engine/configuration/PublicViewProperties.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.configuration; +import com.netgrif.application.engine.authentication.domain.PublicStrategy; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -11,4 +12,5 @@ public class PublicViewProperties { private String url = ""; + private PublicStrategy strategy = PublicStrategy.SIMPLE; } diff --git a/src/main/java/com/netgrif/application/engine/configuration/RBACProperties.java b/src/main/java/com/netgrif/application/engine/configuration/RBACProperties.java new file mode 100644 index 00000000000..9337e9dbe69 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/configuration/RBACProperties.java @@ -0,0 +1,14 @@ +package com.netgrif.application.engine.configuration; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.time.Duration; + +@Data +@Configuration +@ConfigurationProperties(prefix = "role") +public class RBACProperties { + private Duration defaultAssignmentSessionDuration; +} diff --git a/src/main/java/com/netgrif/application/engine/configuration/SessionRegistryConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/SessionRegistryConfiguration.java index 5940986f89f..ca015303376 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/SessionRegistryConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/SessionRegistryConfiguration.java @@ -1,7 +1,5 @@ package com.netgrif.application.engine.configuration; -import com.netgrif.application.engine.configuration.properties.ImpersonationProperties; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.session.FindByIndexNameSessionRepository; @@ -11,17 +9,9 @@ @Configuration public class SessionRegistryConfiguration { - @Autowired - private ImpersonationProperties impersonationProperties; - @Bean public SpringSessionBackedSessionRegistry springSessionBackedSessionRegistry(FindByIndexNameSessionRepository sessionRepository) { return new SpringSessionBackedSessionRegistry<>(sessionRepository); } - @Bean - public String impersonatorRedisHash() { - return impersonationProperties.getRedisNamespace(); - } - } diff --git a/src/main/java/com/netgrif/application/engine/configuration/UserServiceConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/UserServiceConfiguration.java index 8b8f7a5b8a4..30d70b77db7 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/UserServiceConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/UserServiceConfiguration.java @@ -1,10 +1,8 @@ package com.netgrif.application.engine.configuration; -import com.netgrif.application.engine.auth.service.RegistrationService; -import com.netgrif.application.engine.auth.service.UserDetailsServiceImpl; -import com.netgrif.application.engine.auth.service.UserService; -import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.authentication.service.RegistrationService; +import com.netgrif.application.engine.authentication.service.UserDetailsServiceImpl; +import com.netgrif.application.engine.authentication.service.interfaces.IRegistrationService; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -13,21 +11,23 @@ @Configuration public class UserServiceConfiguration { - @Bean - @ConditionalOnMissingBean - public IUserService userService() { - return new UserService(); - } + // todo: release/8.0.0 needed? - @Bean - @ConditionalOnMissingBean - public IRegistrationService registrationService() { - return new RegistrationService(); - } - - @Bean - @ConditionalOnMissingBean - public UserDetailsService userDetailsService() { - return new UserDetailsServiceImpl(); - } +// @Bean +// @ConditionalOnMissingBean +// public IUserService userService() { +// return new UserService(); +// } +// +// @Bean +// @ConditionalOnMissingBean +// public IRegistrationService registrationService() { +// return new RegistrationService(); +// } +// +// @Bean +// @ConditionalOnMissingBean +// public UserDetailsService userDetailsService() { +// return new UserDetailsServiceImpl(); +// } } diff --git a/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/NetgrifAuthenticationProvider.java b/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/NetgrifAuthenticationProvider.java index 64a93f48ca5..dbdfc4c1d10 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/NetgrifAuthenticationProvider.java +++ b/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/NetgrifAuthenticationProvider.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.configuration.authentication.providers; -import com.netgrif.application.engine.auth.service.interfaces.ILoginAttemptService; +import com.netgrif.application.engine.authentication.service.interfaces.ILoginAttemptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.authentication.AuthenticationProvider; diff --git a/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/basic/NetgrifBasicAuthenticationProvider.java b/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/basic/NetgrifBasicAuthenticationProvider.java index 7c9241c227f..4962c856bfd 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/basic/NetgrifBasicAuthenticationProvider.java +++ b/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/basic/NetgrifBasicAuthenticationProvider.java @@ -1,35 +1,36 @@ package com.netgrif.application.engine.configuration.authentication.providers.basic; -import com.netgrif.application.engine.auth.domain.User; -import com.netgrif.application.engine.auth.domain.repositories.UserRepository; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; import com.netgrif.application.engine.configuration.authentication.providers.NetgrifAuthenticationProvider; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.SpringSecurityMessageSource; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.WebAuthenticationDetails; import org.springframework.stereotype.Component; import org.springframework.util.Assert; +import java.util.HashSet; +import java.util.Optional; + @Slf4j @Component +@RequiredArgsConstructor public class NetgrifBasicAuthenticationProvider extends NetgrifAuthenticationProvider { - @Autowired - protected UserRepository userRepository; + protected final IIdentityService identityService; protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); protected PasswordEncoder passwordEncoder; - @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { WebAuthenticationDetails details = (WebAuthenticationDetails) authentication.getDetails(); @@ -42,27 +43,34 @@ public Authentication authenticate(Authentication authentication) throws Authent throw new BadCredentialsException(this.messages .getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } - String name = authentication.getName(); - User user = userRepository.findByEmail(name); - if (user == null) { - log.debug("User not found"); + + Optional identityOpt = identityService.findByUsername(authentication.getName()); + if (identityOpt.isEmpty()) { + log.debug("Identity not found by name"); + loginAttemptService.loginFailed(key); + throw new BadCredentialsException(this.messages + .getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); + } + Identity identity = identityOpt.get(); + if (identity.getAllActors().isEmpty()) { + log.debug("Identity has no available actors"); loginAttemptService.loginFailed(key); throw new BadCredentialsException(this.messages .getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } String presentedPassword = authentication.getCredentials().toString(); - if (!this.passwordEncoder.matches(presentedPassword, user.getPassword())) { + if (!this.passwordEncoder.matches(presentedPassword, identity.getPassword())) { log.debug("Failed to authenticate since password does not match stored value"); loginAttemptService.loginFailed(key); throw new BadCredentialsException(this.messages .getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } - UserDetails userDetails = user.transformToLoggedUser(); + UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(identity.toSession(), + presentedPassword, new HashSet<>()); - UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(userDetails, presentedPassword, userDetails.getAuthorities()); result.setDetails(authentication.getDetails()); - loginAttemptService.loginSucceeded(user.getStringId()); + loginAttemptService.loginSucceeded(key); return result; } diff --git a/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/basic/NetgrifBasicAuthenticationProviderLoader.java b/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/basic/NetgrifBasicAuthenticationProviderLoader.java index ce8785f741c..f89f11e4ae6 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/basic/NetgrifBasicAuthenticationProviderLoader.java +++ b/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/basic/NetgrifBasicAuthenticationProviderLoader.java @@ -1,7 +1,9 @@ package com.netgrif.application.engine.configuration.authentication.providers.basic; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; import com.netgrif.application.engine.configuration.EncryptionConfiguration; import com.netgrif.application.engine.configuration.authentication.providers.NetgrifAuthenticationProvider; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -10,15 +12,16 @@ @Slf4j @Configuration +@RequiredArgsConstructor public class NetgrifBasicAuthenticationProviderLoader { - @Autowired - private EncryptionConfiguration passwordEncoder; + private final EncryptionConfiguration passwordEncoder; + private final IIdentityService identityService; @Lazy @Bean("netgrifBasicAuthenticationProvider") public NetgrifAuthenticationProvider netgrifBasicAuthenticationProvider() { - NetgrifBasicAuthenticationProvider netgrifBasicAuthenticationProvider = new NetgrifBasicAuthenticationProvider(); + NetgrifBasicAuthenticationProvider netgrifBasicAuthenticationProvider = new NetgrifBasicAuthenticationProvider(identityService); netgrifBasicAuthenticationProvider.setPasswordEncoder(passwordEncoder.bCryptPasswordEncoder()); return netgrifBasicAuthenticationProvider; } diff --git a/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/ldap/NetgrifLdapAuthenticationProviderLoader.java b/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/ldap/NetgrifLdapAuthenticationProviderLoader.java index 8c59959cf2e..e41e5ef1b34 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/ldap/NetgrifLdapAuthenticationProviderLoader.java +++ b/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/ldap/NetgrifLdapAuthenticationProviderLoader.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.configuration.authentication.providers.ldap; -import com.netgrif.application.engine.auth.service.interfaces.ILdapUserRefService; +import com.netgrif.application.engine.authentication.service.interfaces.ILdapUserRefService; import com.netgrif.application.engine.configuration.properties.NaeLdapProperties; import com.netgrif.application.engine.ldap.service.LdapUserService; import com.netgrif.application.engine.ldap.service.interfaces.ILdapGroupRefService; diff --git a/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/ldap/UserDetailsContextMapperImpl.java b/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/ldap/UserDetailsContextMapperImpl.java index 6712b1e201d..d4f4bee5b6b 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/ldap/UserDetailsContextMapperImpl.java +++ b/src/main/java/com/netgrif/application/engine/configuration/authentication/providers/ldap/UserDetailsContextMapperImpl.java @@ -1,10 +1,9 @@ package com.netgrif.application.engine.configuration.authentication.providers.ldap; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.ILdapUserRefService; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authentication.service.interfaces.ILdapUserRefService; import com.netgrif.application.engine.configuration.properties.NaeLdapProperties; -import com.netgrif.application.engine.ldap.domain.LdapUser; import com.netgrif.application.engine.ldap.domain.LdapUserRef; import com.netgrif.application.engine.ldap.service.LdapUserService; import com.netgrif.application.engine.ldap.service.interfaces.ILdapGroupRefService; @@ -42,23 +41,24 @@ public UserDetailsContextMapperImpl(LdapUserService ldapUserService, ILdapUserRe @Synchronized public UserDetails mapUserFromContext(DirContextOperations dirContextOperations, String username, Collection authorities) { dirContextOperations.setAttributeValues("objectClass", properties.getPeopleClass()); - IUser user = ldapUserService.findByDn(dirContextOperations.getDn()); - if (user == null) { + Identity identity = ldapUserService.findByDn(dirContextOperations.getDn()); + if (identity == null) { LdapUserRef ldapUserOptional = ldapUserRefService.findById(dirContextOperations.getDn()); if (ldapUserOptional == null) { - log.warn("Unknown user [" + username + "] tried to log in"); + log.warn("Unknown user [{}] tried to log in", username); return null; } - user = ldapUserRefService.createUser(ldapUserOptional); - } else if (user instanceof LdapUser) { - user = ldapUserRefService.updateById(dirContextOperations.getDn(), user); +// identity = ldapUserRefService.createUser(ldapUserOptional); + } else if (true/*user instanceof LdapUser*/) { +// identity = ldapUserRefService.updateById(dirContextOperations.getDn(), user); } - assert user != null; - LoggedUser loggedUser = user.transformToLoggedUser(); - if (user instanceof LdapUser && (!((LdapUser) user).getMemberOf().isEmpty())) { - loggedUser.parseProcessRoles(ldapGroupRefService.getProcessRoleByLdapGroup(((LdapUser) user).getMemberOf())); - } - return loggedUser; + assert identity != null; + LoggedIdentity loggedIdentity = identity.toSession(); +// if (user instanceof LdapUser && (!((LdapUser) user).getMemberOf().isEmpty())) { + // todo: release/8.0.0 +// loggedUser.addRoleAssignments(ldapGroupRefService.getRoleByLdapGroup(((LdapUser) user).getMemberOf())); +// } + return loggedIdentity; } @Override diff --git a/src/main/java/com/netgrif/application/engine/configuration/drools/RuleEngineGlobalsProvider.java b/src/main/java/com/netgrif/application/engine/configuration/drools/RuleEngineGlobalsProvider.java index 9c831b661eb..97009a7122b 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/drools/RuleEngineGlobalsProvider.java +++ b/src/main/java/com/netgrif/application/engine/configuration/drools/RuleEngineGlobalsProvider.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.configuration.drools; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; import com.netgrif.application.engine.configuration.drools.interfaces.IRuleEngineGlobalsProvider; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; @@ -35,6 +36,7 @@ public class RuleEngineGlobalsProvider implements IRuleEngineGlobalsProvider { private final IElasticTaskService elasticTaskService; private final IDataService dataService; private final IMailService mailService; + private final IIdentityService identityService; private final IUserService userService; private final FactRepository factRepository; @@ -45,6 +47,7 @@ public RuleEngineGlobalsProvider(@Autowired IRuleEvaluationScheduleService ruleE @Autowired IElasticTaskService elasticTaskService, @Autowired IDataService dataService, @Autowired IMailService mailService, + @Autowired IIdentityService identityService, @Autowired IUserService userService, @Autowired FactRepository factRepository) { this.ruleEvaluationScheduleService = ruleEvaluationScheduleService; @@ -54,6 +57,7 @@ public RuleEngineGlobalsProvider(@Autowired IRuleEvaluationScheduleService ruleE this.elasticTaskService = elasticTaskService; this.dataService = dataService; this.mailService = mailService; + this.identityService = identityService; this.userService = userService; this.factRepository = factRepository; } @@ -67,7 +71,8 @@ void postConstruct() { protected List initializeGlobals() { List globals = new ArrayList<>(); globals.add(engineGlobal("com.netgrif.application.engine.workflow.service.interfaces", "ITaskService", "taskService", taskService)); - globals.add(engineGlobal("com.netgrif.application.engine.auth.service.interfaces", "IUserService", "userService", userService)); + globals.add(engineGlobal("com.netgrif.application.engine.authentication.service.interfaces", "IIdentityService", "identityService", identityService)); + globals.add(engineGlobal("com.netgrif.application.engine.authorization.service.interfaces", "IUserService", "userService", userService)); globals.add(engineGlobal("com.netgrif.application.engine.elastic.service.interfaces", "IElasticCaseService", "elasticCaseService", elasticCaseService)); globals.add(engineGlobal("com.netgrif.application.engine.elastic.service.interfaces", "IElasticTaskService", "elasticTaskService", elasticTaskService)); globals.add(engineGlobal("com.netgrif.application.engine.rules.domain", "FactRepository", "factRepository", factRepository)); diff --git a/src/main/java/com/netgrif/application/engine/configuration/mongo/MongoConfig.java b/src/main/java/com/netgrif/application/engine/configuration/mongo/MongoConfig.java new file mode 100644 index 00000000000..38121472f5e --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/configuration/mongo/MongoConfig.java @@ -0,0 +1,27 @@ +package com.netgrif.application.engine.configuration.mongo; + +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.autoconfigure.mongo.MongoProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.MongoTransactionManager; +import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; + +@Configuration +@RequiredArgsConstructor +public class MongoConfig extends AbstractMongoClientConfiguration { + + private final MongoProperties properties; + + @Bean + public MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) { + return new MongoTransactionManager(dbFactory); + } + + @Override + protected @NonNull String getDatabaseName() { + return properties.getDatabase(); + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/configuration/properties/ImpersonationProperties.java b/src/main/java/com/netgrif/application/engine/configuration/properties/ImpersonationProperties.java deleted file mode 100644 index 92aef995bdf..00000000000 --- a/src/main/java/com/netgrif/application/engine/configuration/properties/ImpersonationProperties.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.netgrif.application.engine.configuration.properties; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Data -@Configuration -@ConfigurationProperties(prefix = "nae.impersonation") -public class ImpersonationProperties { - - private String redisNamespace; - private boolean enabled; - private int configsPerUser = 1000; - -} diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/AuthenticationService.java b/src/main/java/com/netgrif/application/engine/configuration/security/AuthenticationService.java index 1026df00dc2..8efe99d5f0e 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/security/AuthenticationService.java +++ b/src/main/java/com/netgrif/application/engine/configuration/security/AuthenticationService.java @@ -1,32 +1,25 @@ package com.netgrif.application.engine.configuration.security; -import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.configuration.security.interfaces.IAuthenticationService; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.ApplicationListener; import org.springframework.context.event.EventListener; import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent; import org.springframework.security.authentication.event.AuthenticationSuccessEvent; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.session.SessionDestroyedEvent; import org.springframework.security.web.authentication.WebAuthenticationDetails; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; -import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @Slf4j @Service -public class AuthenticationService implements IAuthenticationService, ApplicationListener { +public class AuthenticationService implements IAuthenticationService { @Value("${server.login.attempts:10}") @@ -37,9 +30,6 @@ public class AuthenticationService implements IAuthenticationService, Applicatio private ConcurrentMap cache; - @Autowired - private IImpersonationService impersonationService; - public AuthenticationService() { super(); cache = new ConcurrentHashMap<>(); @@ -50,7 +40,6 @@ public static String getClientIP(HttpServletRequest request) { if (xHeader == null) return request.getRemoteAddr(); return xHeader.split(",")[0]; - } @EventListener @@ -61,13 +50,6 @@ public void onAuthenticationFailure(AuthenticationFailureBadCredentialsEvent eve @EventListener public void onAuthenticationSuccess(AuthenticationSuccessEvent event) { loginSucceeded(((WebAuthenticationDetails) event.getAuthentication().getDetails()).getRemoteAddress()); - resolveImpersonatorOnLogin(event.getAuthentication().getPrincipal()); - } - - @Override - public void onApplicationEvent(SessionDestroyedEvent event) { - List contexts = event.getSecurityContexts(); - contexts.forEach(context -> resolveImpersonatorOnLogout(context.getAuthentication().getPrincipal())); } @Override @@ -101,26 +83,6 @@ private void timeout(String key) { } - protected void resolveImpersonatorOnLogin(Object principal) { - try { - if (principal instanceof LoggedUser) { - impersonationService.removeImpersonator(((LoggedUser) principal).getId()); - } - } catch (Exception e) { - log.warn("Failed to resolve impersonator " + principal, e); - } - } - - protected void resolveImpersonatorOnLogout(Object principal) { - try { - if (principal instanceof LoggedUser && ((LoggedUser) principal).isImpersonating()) { - impersonationService.onSessionDestroy((LoggedUser) principal); - } - } catch (Exception e) { - log.warn("Failed to resolve impersonator " + principal, e); - } - } - @Data public class Attempt { diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/ImpersonationRequestFilter.java b/src/main/java/com/netgrif/application/engine/configuration/security/ImpersonationRequestFilter.java deleted file mode 100644 index 315e3591c1e..00000000000 --- a/src/main/java/com/netgrif/application/engine/configuration/security/ImpersonationRequestFilter.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.netgrif.application.engine.configuration.security; - -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.impersonation.domain.Impersonator; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.time.LocalDateTime; -import java.util.Optional; - -@Slf4j -public class ImpersonationRequestFilter extends OncePerRequestFilter { - - private final IImpersonationService impersonationService; - - public ImpersonationRequestFilter(IImpersonationService impersonationService) { - this.impersonationService = impersonationService; - } - - @Override - public void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { - try { - LoggedUser loggedUser = getPrincipal(); - if (loggedUser != null) { - handleImpersonated(loggedUser, servletRequest); - handleImpersonator(loggedUser, servletRequest, servletResponse); - } - } catch (Exception e) { - log.error("Filter error", e); - } - - filterChain.doFilter(servletRequest, servletResponse); - } - - protected void handleImpersonator(LoggedUser loggedUser, HttpServletRequest servletRequest, HttpServletResponse servletResponse) { - try { - if (!loggedUser.isImpersonating()) { - return; - } - Optional imp = impersonationService.findImpersonator(loggedUser.getId()); - if (loggedUser.isImpersonating() && (imp.isEmpty() || !isValid(imp.get()))) { - imp.ifPresent(imper -> impersonationService.removeImpersonator(loggedUser.getId())); - logout(servletRequest, servletResponse); - } - } catch (Exception e) { - log.error("ImpersonationRequestFilter error {}", e.getMessage(), e); - } - } - - protected void handleImpersonated(LoggedUser loggedUser, HttpServletRequest servletRequest) { - try { - log.debug("Filtering request {}, {}", servletRequest.getRequestURI(), loggedUser.getUsername()); - impersonationService.removeImpersonatorByImpersonated(loggedUser.getId()); - } catch (Exception e) { - log.error("Failed to resolve impersonators for {}, {}", loggedUser.getUsername(), e.getMessage(), e); - } - } - - protected boolean isValid(Impersonator impersonator) { - if (impersonator.getImpersonatingUntil() == null) { - return true; - } - return !LocalDateTime.now().isAfter(impersonator.getImpersonatingUntil()); - } - - protected LoggedUser getPrincipal() { - Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - if (auth == null) { - return null; - } - - Object principal = auth.getPrincipal(); - if (!(principal instanceof LoggedUser)) { - log.warn("{} is not an instance of LoggedUser", principal); - return null; - } - - return (LoggedUser) auth.getPrincipal(); - } - - protected void logout(HttpServletRequest request, HttpServletResponse response) { - new SecurityContextLogoutHandler().logout(request, response, null); - } - - -} diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/PublicAdvancedAuthenticationFilter.java b/src/main/java/com/netgrif/application/engine/configuration/security/PublicAdvancedAuthenticationFilter.java new file mode 100644 index 00000000000..e1d1654713a --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/configuration/security/PublicAdvancedAuthenticationFilter.java @@ -0,0 +1,59 @@ +package com.netgrif.application.engine.configuration.security; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.constants.AnonymIdentityConstants; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.configuration.security.jwt.IJwtService; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.startup.AnonymousIdentityRunner; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; +import lombok.extern.slf4j.Slf4j; +import org.bson.types.ObjectId; +import org.springframework.security.authentication.AnonymousAuthenticationProvider; +import org.springframework.security.authentication.ProviderManager; + +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * todo javadoc + */ +@Slf4j +public class PublicAdvancedAuthenticationFilter extends PublicJwtAuthenticationFilter { + + public PublicAdvancedAuthenticationFilter(IIdentityService identityService, ProviderManager authenticationManager, + AnonymousAuthenticationProvider provider, String[] urls, String[] exceptions, + IJwtService jwtService, IRoleService roleService) { + super(identityService, authenticationManager, provider, urls, exceptions, jwtService, roleService); + } + + /** + * todo javadoc + */ + @Override + protected Identity getAnonymousIdentityWithUser() { + String hash = new ObjectId().toString(); + + Optional anonymIdentityOpt = identityService.findByUsername(AnonymIdentityConstants.usernameOf(hash)); + if (anonymIdentityOpt.isPresent()) { + return anonymIdentityOpt.get(); + } + + Identity identity = identityService.createWithDefaultUser(IdentityParams.with() + .username(new TextField(AnonymIdentityConstants.usernameOf(hash))) + .firstname(new TextField(AnonymIdentityConstants.FIRSTNAME)) + .lastname(new TextField(AnonymIdentityConstants.LASTNAME)) + .password(new TextField("n/a")) + .properties(Map.of(AnonymousIdentityRunner.getAnonymousFlag(), "true")) + .build()); + + Set roleIds = Set.of(roleService.findApplicationRoleByImportId(ApplicationRoleRunner.ANONYMOUS_APP_ROLE).getStringId(), + roleService.findAnonymousRole().getStringId()); + roleService.assignRolesToActor(identity.getMainActorId(), roleIds); + + return identity; + } +} diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/PublicAuthenticationFilter.java b/src/main/java/com/netgrif/application/engine/configuration/security/PublicAuthenticationFilter.java index c08458e057d..8fd02d03dad 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/security/PublicAuthenticationFilter.java +++ b/src/main/java/com/netgrif/application/engine/configuration/security/PublicAuthenticationFilter.java @@ -1,11 +1,10 @@ package com.netgrif.application.engine.configuration.security; -import com.netgrif.application.engine.auth.domain.*; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.configuration.security.jwt.IJwtService; -import io.jsonwebtoken.ExpiredJwtException; +import com.netgrif.application.engine.authentication.domain.*; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; import lombok.extern.slf4j.Slf4j; -import org.bson.types.ObjectId; import org.springframework.security.authentication.AnonymousAuthenticationProvider; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.AuthenticationDetailsSource; @@ -15,117 +14,46 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.web.filter.OncePerRequestFilter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; +import java.util.Set; @Slf4j -public class PublicAuthenticationFilter extends OncePerRequestFilter { +public abstract class PublicAuthenticationFilter extends OncePerRequestFilter { - private final static String JWT_HEADER_NAME = "X-Jwt-Token"; - private final static String BEARER = "Bearer "; - private final ProviderManager authenticationManager; - private final AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); - private final Authority anonymousAuthority; - private final String[] anonymousAccessUrls; - private final String[] exceptions; - - private final IJwtService jwtService; - private final IUserService userService; + protected final IIdentityService identityService; + protected final IRoleService roleService; + protected final ProviderManager authenticationManager; + protected final AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); + protected final String[] anonymousAccessUrls; + protected final String[] exceptions; public PublicAuthenticationFilter(ProviderManager authenticationManager, AnonymousAuthenticationProvider provider, - Authority anonymousAuthority, String[] urls, String[] exceptions, IJwtService jwtService, - IUserService userService) { + String[] urls, String[] exceptions, IIdentityService identityService, IRoleService roleService) { + this.identityService = identityService; this.authenticationManager = authenticationManager; + this.roleService = roleService; this.authenticationManager.getProviders().add(provider); - this.anonymousAuthority = anonymousAuthority; this.anonymousAccessUrls = urls; this.exceptions = exceptions; - this.jwtService = jwtService; - this.userService = userService; } - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - if (isPublicApi(request.getRequestURI())) { - String jwtToken = resolveValidToken(request, response); - authenticate(request, jwtToken); - response.setHeader(JWT_HEADER_NAME, BEARER + jwtToken); - log.info("Anonymous user was authenticated."); - } - filterChain.doFilter(request, response); - } + protected abstract Identity getAnonymousIdentityWithUser(); - private void authenticate(HttpServletRequest request, String jwtToken) { + protected void authenticate(HttpServletRequest request, LoggedIdentity loggedIdentity) { AnonymousAuthenticationToken authRequest = new AnonymousAuthenticationToken( - UserProperties.ANONYMOUS_AUTH_KEY, - jwtService.getLoggedUser(jwtToken, this.anonymousAuthority), - Collections.singleton(this.anonymousAuthority) + IdentityProperties.ANONYMOUS_AUTH_KEY, + loggedIdentity, + Set.of(roleService.findApplicationRoleByImportId(ApplicationRoleRunner.ANONYMOUS_APP_ROLE)) ); authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request)); Authentication authResult = this.authenticationManager.authenticate(authRequest); SecurityContextHolder.getContext().setAuthentication(authResult); } - private String resolveValidToken(HttpServletRequest request, HttpServletResponse response) { - Map claims = new HashMap<>(); - String jwtHeader = request.getHeader(JWT_HEADER_NAME); - String jwtToken; - - if (jwtHeader == null || !jwtHeader.startsWith(BEARER)) { - log.warn("There is no JWT token or token is invalid."); - resolveClaims(claims, request); - jwtToken = jwtService.tokenFrom(claims); - } else { - jwtToken = jwtHeader.replace(BEARER, ""); - } - - try { - jwtService.isExpired(jwtToken); - } catch (ExpiredJwtException e) { - claims = e.getClaims(); - resolveClaims(claims, request); - jwtToken = jwtService.tokenFrom(claims); - } - - return jwtToken; - } - - private void resolveClaims(Map claims, HttpServletRequest request) { - LoggedUser loggedUser = createAnonymousUser(request); - - if (claims.containsKey("user")) { - IUser user = userService.findAnonymousByEmail((String) ((LinkedHashMap) claims.get("user")).get("email")); - if (user != null) { - loggedUser = user.transformToLoggedUser(); - } - } - loggedUser.eraseCredentials(); - claims.put("user", loggedUser); - } - - private LoggedUser createAnonymousUser(HttpServletRequest request) { - String hash = new ObjectId().toString(); - - // TODO: release/8.0.0 string constants, properties? - AnonymousUser anonymousUser = (AnonymousUser) this.userService.findAnonymousByEmail(hash + "@nae.com"); - - if (anonymousUser == null) { - anonymousUser = new AnonymousUser(hash + "@anonymous.nae", - "n/a", - "User", - "Anonymous" - ); - anonymousUser.setState(UserState.ACTIVE); - userService.saveNewAnonymous(anonymousUser); - } - return anonymousUser.transformToLoggedUser(); - } - - private boolean isPublicApi(String path) { + /** + * todo javadoc + */ + protected boolean isPublicApi(String path) { for (String url : this.anonymousAccessUrls) { if (path.matches(url.replace("*", ".*?"))) { for (String ex : this.exceptions) { diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/PublicBasicAuthenticationFilter.java b/src/main/java/com/netgrif/application/engine/configuration/security/PublicBasicAuthenticationFilter.java new file mode 100644 index 00000000000..2e315ba0e62 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/configuration/security/PublicBasicAuthenticationFilter.java @@ -0,0 +1,63 @@ +package com.netgrif.application.engine.configuration.security; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.constants.AnonymIdentityConstants; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.domain.User; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; +import com.netgrif.application.engine.configuration.security.jwt.IJwtService; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.startup.AnonymousIdentityRunner; +import lombok.extern.slf4j.Slf4j; +import org.bson.types.ObjectId; +import org.springframework.security.authentication.AnonymousAuthenticationProvider; +import org.springframework.security.authentication.ProviderManager; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * todo javadoc + */ +@Slf4j +public class PublicBasicAuthenticationFilter extends PublicJwtAuthenticationFilter { + + private final IUserService userService; + + public PublicBasicAuthenticationFilter(IIdentityService identityService, ProviderManager authenticationManager, + AnonymousAuthenticationProvider provider, String[] urls, String[] exceptions, + IJwtService jwtService, IUserService userService, IRoleService roleService) { + super(identityService, authenticationManager, provider, urls, exceptions, jwtService, roleService); + this.userService = userService; + } + + /** + * todo javadoc + */ + @Override + protected Identity getAnonymousIdentityWithUser() { + String hash = new ObjectId().toString(); + + Optional anonymIdentityOpt = identityService.findByUsername(AnonymIdentityConstants.usernameOf(hash)); + if (anonymIdentityOpt.isPresent()) { + return anonymIdentityOpt.get(); + } + + Optional anonymUserOpt = userService.findByEmail(AnonymIdentityConstants.defaultUsername()); + User anonymUser = anonymUserOpt.orElseThrow(() -> new IllegalStateException(String.format( + "Default anonymous user with email [%s] doesn't exist", AnonymIdentityConstants.defaultUsername()))); + + return identityService.encodePasswordAndCreate(IdentityParams.with() + .username(new TextField(AnonymIdentityConstants.usernameOf(hash))) + .firstname(new TextField(AnonymIdentityConstants.FIRSTNAME)) + .lastname(new TextField(AnonymIdentityConstants.LASTNAME)) + .password(new TextField("n/a")) + .mainActor(CaseField.withValue(List.of(anonymUser.getStringId()))) + .properties(Map.of(AnonymousIdentityRunner.getAnonymousFlag(), "true")) + .build()); + } +} diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/PublicJwtAuthenticationFilter.java b/src/main/java/com/netgrif/application/engine/configuration/security/PublicJwtAuthenticationFilter.java new file mode 100644 index 00000000000..41233117d21 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/configuration/security/PublicJwtAuthenticationFilter.java @@ -0,0 +1,96 @@ +package com.netgrif.application.engine.configuration.security; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.configuration.security.jwt.IJwtService; +import io.jsonwebtoken.ExpiredJwtException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.lang.NonNull; +import org.springframework.security.authentication.AnonymousAuthenticationProvider; +import org.springframework.security.authentication.ProviderManager; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; + +@Slf4j +public abstract class PublicJwtAuthenticationFilter extends PublicAuthenticationFilter { + protected final static String JWT_HEADER_NAME = "X-Jwt-Token"; + protected final static String BEARER = "Bearer "; + + protected final IJwtService jwtService; + + public PublicJwtAuthenticationFilter(IIdentityService identityService, ProviderManager authenticationManager, + AnonymousAuthenticationProvider provider, String[] urls, String[] exceptions, + IJwtService jwtService, IRoleService roleService) { + super(authenticationManager, provider, urls, exceptions, identityService, roleService); + this.jwtService = jwtService; + } + + /** + * todo javadoc + */ + @Override + protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) throws ServletException, IOException { + if (isPublicApi(request.getRequestURI())) { + String jwtToken = resolveValidToken(request); + authenticate(request, jwtService.getLoggedIdentity(jwtToken)); + response.setHeader(JWT_HEADER_NAME, BEARER + jwtToken); + log.info("Anonymous identity was authenticated."); + } + filterChain.doFilter(request, response); + } + + /** + * todo javadoc + */ + protected String resolveValidToken(HttpServletRequest request) { + Map claims = new HashMap<>(); + String jwtHeader = request.getHeader(JWT_HEADER_NAME); + String jwtToken; + + if (jwtHeader == null || !jwtHeader.startsWith(BEARER)) { + log.warn("There is no JWT token or token is invalid."); + resolveClaims(claims); + jwtToken = jwtService.tokenFrom(claims); + } else { + jwtToken = jwtHeader.replace(BEARER, ""); + } + + try { + jwtService.isExpired(jwtToken); + } catch (ExpiredJwtException e) { + claims = e.getClaims(); + resolveClaims(claims); + jwtToken = jwtService.tokenFrom(claims); + } + + return jwtToken; + } + + /** + * todo javadoc + */ + protected void resolveClaims(Map claims) { + Optional identityOpt = Optional.empty(); + + if (claims.containsKey("identity")) { + identityOpt = identityService.findByUsername((String) ((LinkedHashMap) claims.get("identity")).get("username")); + } + + Identity identity = identityOpt.orElseGet(this::getAnonymousIdentityWithUser); + + LoggedIdentity loggedIdentity = identity.toSession(); + loggedIdentity.eraseCredentials(); + + claims.put("identity", loggedIdentity); + } +} diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/PublicSimpleAuthenticationFilter.java b/src/main/java/com/netgrif/application/engine/configuration/security/PublicSimpleAuthenticationFilter.java new file mode 100644 index 00000000000..0278576b0f1 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/configuration/security/PublicSimpleAuthenticationFilter.java @@ -0,0 +1,59 @@ +package com.netgrif.application.engine.configuration.security; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.constants.AnonymIdentityConstants; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.lang.NonNull; +import org.springframework.security.authentication.AnonymousAuthenticationProvider; +import org.springframework.security.authentication.ProviderManager; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Optional; + +/** + * todo javadoc + */ +@Slf4j +public class PublicSimpleAuthenticationFilter extends PublicAuthenticationFilter { + + + public PublicSimpleAuthenticationFilter(IIdentityService identityService, ProviderManager authenticationManager, + AnonymousAuthenticationProvider provider, String[] urls, String[] exceptions, + IRoleService roleService) { + super(authenticationManager, provider, urls, exceptions, identityService, roleService); + } + + /** + * todo javadoc + */ + @Override + protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServletResponse response, + @NonNull FilterChain filterChain) throws ServletException, IOException { + if (isPublicApi(request.getRequestURI())) { + Identity identity = getAnonymousIdentityWithUser(); + authenticate(request, identity.toSession()); + log.info("Anonymous identity was authenticated."); + } + filterChain.doFilter(request, response); + } + + /** + * todo javadoc + */ + @Override + protected Identity getAnonymousIdentityWithUser() { + Optional anonymIdentityOpt = identityService.findByUsername(AnonymIdentityConstants.defaultUsername()); + if (anonymIdentityOpt.isPresent()) { + return anonymIdentityOpt.get(); + } else { + throw new IllegalStateException(String.format("Default anonymous identity with username [%s] doesn't exist", + AnonymIdentityConstants.defaultUsername())); + } + } +} diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/SecurityContextFilter.java b/src/main/java/com/netgrif/application/engine/configuration/security/SecurityContextFilter.java index 50295ff091a..68674dcf207 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/security/SecurityContextFilter.java +++ b/src/main/java/com/netgrif/application/engine/configuration/security/SecurityContextFilter.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.configuration.security; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.security.service.ISecurityContextService; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.context.SecurityContextHolder; @@ -32,8 +32,8 @@ public SecurityContextFilter(ISecurityContextService securityContextService) { */ @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - if (securityContextService.isAuthenticatedPrincipalLoggedUser()) - securityContextService.forceReloadSecurityContext((LoggedUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal()); + if (securityContextService.isAuthenticatedPrincipalLoggedIdentity()) + securityContextService.forceReloadSecurityContext((LoggedIdentity) SecurityContextHolder.getContext().getAuthentication().getPrincipal()); filterChain.doFilter(request, response); } } diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/factory/AdvancedPublicAuthenticationFilterFactory.java b/src/main/java/com/netgrif/application/engine/configuration/security/factory/AdvancedPublicAuthenticationFilterFactory.java new file mode 100644 index 00000000000..a627bef835d --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/configuration/security/factory/AdvancedPublicAuthenticationFilterFactory.java @@ -0,0 +1,33 @@ +package com.netgrif.application.engine.configuration.security.factory; + +import com.netgrif.application.engine.authentication.domain.IdentityProperties; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.configuration.authentication.providers.NaeAuthProperties; +import com.netgrif.application.engine.configuration.security.PublicAdvancedAuthenticationFilter; +import com.netgrif.application.engine.configuration.security.PublicAuthenticationFilter; +import com.netgrif.application.engine.configuration.security.jwt.IJwtService; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.security.authentication.AnonymousAuthenticationProvider; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.stereotype.Service; + +@Service +@ConditionalOnProperty(prefix = "nae.public", name = "strategy", havingValue = "advanced") +public class AdvancedPublicAuthenticationFilterFactory extends PublicAuthenticationFilterFactory { + + private final IJwtService jwtService; + + public AdvancedPublicAuthenticationFilterFactory(IIdentityService identityService, IRoleService roleService, + NaeAuthProperties naeAuthProperties, IJwtService jwtService) { + super(identityService, roleService, naeAuthProperties); + this.jwtService = jwtService; + } + + @Override + protected PublicAuthenticationFilter doCreateFilter(ProviderManager authManager) { + return new PublicAdvancedAuthenticationFilter(identityService, authManager, + new AnonymousAuthenticationProvider(IdentityProperties.ANONYMOUS_AUTH_KEY), + naeAuthProperties.getServerPatterns(), naeAuthProperties.getAnonymousExceptions(), jwtService, roleService); + } +} diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/factory/BasicPublicAuthenticationFilterFactory.java b/src/main/java/com/netgrif/application/engine/configuration/security/factory/BasicPublicAuthenticationFilterFactory.java new file mode 100644 index 00000000000..ba82c845660 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/configuration/security/factory/BasicPublicAuthenticationFilterFactory.java @@ -0,0 +1,37 @@ +package com.netgrif.application.engine.configuration.security.factory; + +import com.netgrif.application.engine.authentication.domain.IdentityProperties; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.configuration.authentication.providers.NaeAuthProperties; +import com.netgrif.application.engine.configuration.security.PublicAuthenticationFilter; +import com.netgrif.application.engine.configuration.security.PublicBasicAuthenticationFilter; +import com.netgrif.application.engine.configuration.security.jwt.IJwtService; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.security.authentication.AnonymousAuthenticationProvider; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.stereotype.Service; + +@Service +@ConditionalOnProperty(prefix = "nae.public", name = "strategy", havingValue = "basic") +public class BasicPublicAuthenticationFilterFactory extends PublicAuthenticationFilterFactory { + + private final IJwtService jwtService; + private final IUserService userService; + + public BasicPublicAuthenticationFilterFactory(IIdentityService identityService, IRoleService roleService, + NaeAuthProperties naeAuthProperties, IJwtService jwtService, IUserService userService) { + super(identityService, roleService, naeAuthProperties); + this.jwtService = jwtService; + this.userService = userService; + } + + @Override + protected PublicAuthenticationFilter doCreateFilter(ProviderManager authManager) { + return new PublicBasicAuthenticationFilter(identityService, authManager, + new AnonymousAuthenticationProvider(IdentityProperties.ANONYMOUS_AUTH_KEY), + naeAuthProperties.getServerPatterns(), naeAuthProperties.getAnonymousExceptions(), jwtService, + userService, roleService); + } +} diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/factory/PublicAuthenticationFilterFactory.java b/src/main/java/com/netgrif/application/engine/configuration/security/factory/PublicAuthenticationFilterFactory.java new file mode 100644 index 00000000000..83419734575 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/configuration/security/factory/PublicAuthenticationFilterFactory.java @@ -0,0 +1,35 @@ +package com.netgrif.application.engine.configuration.security.factory; + +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.configuration.authentication.providers.NaeAuthProperties; +import com.netgrif.application.engine.configuration.security.PublicAuthenticationFilter; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.ProviderManager; + +@RequiredArgsConstructor +public abstract class PublicAuthenticationFilterFactory { + + protected final IIdentityService identityService; + protected final IRoleService roleService; + protected final NaeAuthProperties naeAuthProperties; + + private PublicAuthenticationFilter singletonFilter; + + /** + * todo javadoc + * */ + protected abstract PublicAuthenticationFilter doCreateFilter(ProviderManager authManager); + + /** + * todo javadoc + * */ + public PublicAuthenticationFilter createFilter(ProviderManager authManager) { + if (this.singletonFilter != null) { + return this.singletonFilter; + } + + this.singletonFilter = doCreateFilter(authManager); + return this.singletonFilter; + } +} diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/factory/SimplePublicAuthenticationFilterFactory.java b/src/main/java/com/netgrif/application/engine/configuration/security/factory/SimplePublicAuthenticationFilterFactory.java new file mode 100644 index 00000000000..dea4b0da140 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/configuration/security/factory/SimplePublicAuthenticationFilterFactory.java @@ -0,0 +1,29 @@ +package com.netgrif.application.engine.configuration.security.factory; + +import com.netgrif.application.engine.authentication.domain.IdentityProperties; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.configuration.authentication.providers.NaeAuthProperties; +import com.netgrif.application.engine.configuration.security.PublicAuthenticationFilter; +import com.netgrif.application.engine.configuration.security.PublicSimpleAuthenticationFilter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.security.authentication.AnonymousAuthenticationProvider; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.stereotype.Service; + +@Service +@ConditionalOnProperty(prefix = "nae.public", name = "strategy", havingValue = "simple") +public class SimplePublicAuthenticationFilterFactory extends PublicAuthenticationFilterFactory { + + public SimplePublicAuthenticationFilterFactory(IIdentityService identityService, IRoleService roleService, + NaeAuthProperties naeAuthProperties) { + super(identityService, roleService, naeAuthProperties); + } + + @Override + public PublicAuthenticationFilter doCreateFilter(ProviderManager authManager) { + return new PublicSimpleAuthenticationFilter(identityService, authManager, + new AnonymousAuthenticationProvider(IdentityProperties.ANONYMOUS_AUTH_KEY), + naeAuthProperties.getServerPatterns(), naeAuthProperties.getAnonymousExceptions(), roleService); + } +} diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/jwt/IJwtService.java b/src/main/java/com/netgrif/application/engine/configuration/security/jwt/IJwtService.java index 724089a3dfb..f7a38ab8724 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/security/jwt/IJwtService.java +++ b/src/main/java/com/netgrif/application/engine/configuration/security/jwt/IJwtService.java @@ -1,7 +1,6 @@ package com.netgrif.application.engine.configuration.security.jwt; -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import java.util.Map; @@ -10,5 +9,5 @@ public interface IJwtService { void isExpired(String token); - LoggedUser getLoggedUser(String token, Authority anonymousRole); + LoggedIdentity getLoggedIdentity(String token); } diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/jwt/JwtService.java b/src/main/java/com/netgrif/application/engine/configuration/security/jwt/JwtService.java index 60d5757b456..ebbcbc76112 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/security/jwt/JwtService.java +++ b/src/main/java/com/netgrif/application/engine/configuration/security/jwt/JwtService.java @@ -1,14 +1,12 @@ package com.netgrif.application.engine.configuration.security.jwt; -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; @@ -20,15 +18,12 @@ @Slf4j @Service +@RequiredArgsConstructor public class JwtService implements IJwtService { - + // todo javadoc everywhere private String secret = ""; - @Autowired - private JwtProperties properties; - - @Autowired - private IProcessRoleService roleService; + private final JwtProperties properties; @PostConstruct private void resolveSecret() { @@ -36,7 +31,7 @@ private void resolveSecret() { PrivateKeyReader reader = new PrivateKeyReader(properties.getAlgorithm()); secret = Base64.getEncoder().encodeToString(reader.get(properties.getPrivateKey().getFile().getPath()).getEncoded()); } catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) { - log.error("Error while resolving secret key: " + e.getMessage(), e); + log.error("Error while resolving secret key: {}", e.getMessage(), e); } } @@ -53,27 +48,26 @@ public void isExpired(String token) throws ExpiredJwtException { } @Override - public LoggedUser getLoggedUser(String token, Authority anonymousAuthority) { - LinkedHashMap userMap = (LinkedHashMap) getAllClaimsFromToken(token).get("user"); - LoggedUser user = new LoggedUser( - userMap.get("id").toString(), - userMap.get("username").toString(), - "n/a", - Collections.singleton(anonymousAuthority) - ); - user.setFullName(userMap.get("fullName").toString()); - user.setAnonymous((boolean) userMap.get("anonymous")); - user.setProcessRoles(Collections.singleton(roleService.anonymousRole().getStringId())); - return user; + @SuppressWarnings("unchecked") + public LoggedIdentity getLoggedIdentity(String token) { + LinkedHashMap loggedIdentityMap = (LinkedHashMap) getAllClaimsFromToken(token).get("identity"); + return LoggedIdentity.with() + .identityId(loggedIdentityMap.get("identityId").toString()) + .username(loggedIdentityMap.get("username").toString()) + .password("n/a") + .fullName(loggedIdentityMap.get("fullName").toString()) + .activeActorId(loggedIdentityMap.get("activeActorId").toString()) + .properties((Map) loggedIdentityMap.get("properties")) + .build(); } - private Date getExpirationDateFromToken(String token) throws ExpiredJwtException { - return getClaimFromToken(token, Claims::getExpiration); + private void getExpirationDateFromToken(String token) throws ExpiredJwtException { + getClaimFromToken(token, Claims::getExpiration); } - private T getClaimFromToken(String token, Function claimsResolver) throws ExpiredJwtException { + private void getClaimFromToken(String token, Function claimsResolver) throws ExpiredJwtException { final Claims claims = getAllClaimsFromToken(token); - return claimsResolver.apply(claims); + claimsResolver.apply(claims); } private Claims getAllClaimsFromToken(String token) throws ExpiredJwtException { diff --git a/src/main/java/com/netgrif/application/engine/elastic/ElasticMappingUtils.java b/src/main/java/com/netgrif/application/engine/elastic/ElasticMappingUtils.java new file mode 100644 index 00000000000..ecd8c45a3ae --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/elastic/ElasticMappingUtils.java @@ -0,0 +1,33 @@ +package com.netgrif.application.engine.elastic; + +import com.netgrif.application.engine.authorization.domain.permissions.AccessPermissions; + +import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public class ElasticMappingUtils { + + /** + * todo javadoc + * */ + public static Set filterRoleIdsByPermissionValue(AccessPermissions permissions, T permission, boolean isPositive) { + return filterRoleIds(permissions, (permissionEntry) -> + permissionEntry.getValue().containsKey(permission) && permissionEntry.getValue().get(permission) == isPositive); + } + + /** + * todo javadoc + * */ + public static Set filterRoleIdsByPermissionType(AccessPermissions permissions, T permission) { + return filterRoleIds(permissions, (permissionEntry) -> permissionEntry.getValue().containsKey(permission)); + } + + protected static Set filterRoleIds(AccessPermissions permissions, Predicate>> predicate) { + return permissions.getPermissions().entrySet().stream() + .filter(predicate) + .map(Map.Entry::getKey) + .collect(Collectors.toSet()); + } +} diff --git a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticCase.java b/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticCase.java index ebe113ea85c..cbcb626f409 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticCase.java +++ b/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticCase.java @@ -19,7 +19,6 @@ import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -63,14 +62,11 @@ public class ElasticCase { private Long creationDateSortable; - @Field(type = Keyword) - private String author; - @Field(type = Keyword) private String mongoId; @Field(type = Keyword) - private String authorName; + private String authorId; @Field(type = Keyword) private String authorEmail; @@ -84,31 +80,31 @@ public class ElasticCase { private Set taskMongoIds; @Field(type = Keyword) - private Set enabledRoles; + private Set viewProcessRoles; @Field(type = Keyword) - private Set viewRoles; + private Set positiveViewProcessRoles; @Field(type = Keyword) - private Set viewUserRefs; + private Set negativeViewProcessRoles; @Field(type = Keyword) - private Set negativeViewRoles; + private Set viewCaseRoles; - private Set viewUsers; + private Set positiveViewCaseRoles; @Field(type = Keyword) - private Set negativeViewUsers; + private Set negativeViewCaseRoles; private Map tags; /** * Data that is stored in the elasticsearch database. * - * Note that the dataSet attribute is NOT set when the object is created and must be set later. + * Note that the dataSet and permissions attributes are NOT set when the object is created and must be set later. * - * The {@link com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseMappingService IElasticCaseMappingService} can be used to create - * instances of this class from Case objects, that have the dataset populated. + * The {@link com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseMappingService IElasticCaseMappingService} + * can be used to create instances of this class from Case objects, that have the dataset populated. * * @param useCase the data object that should be turned into elasticsearch data object */ @@ -119,22 +115,17 @@ public ElasticCase(Case useCase) { lastModified = Timestamp.valueOf(useCase.getLastModified()).getTime(); processIdentifier = useCase.getProcessIdentifier(); processId = useCase.getPetriNetId(); - visualId = useCase.getVisualId(); +// TODO: release/8.0.0 +// visualId = useCase.getVisualId(); title = useCase.getTitle(); creationDate = useCase.getCreationDate(); creationDateSortable = Timestamp.valueOf(useCase.getCreationDate()).getTime(); - author = useCase.getAuthor().getId(); - authorName = useCase.getAuthor().getFullName(); - authorEmail = useCase.getAuthor().getEmail(); + authorId = useCase.getAuthorId(); + // todo: release/8.0.0 +// authorEmail = useCase.getAuthorId().getEmail(); taskIds = useCase.getTasks().keySet(); taskMongoIds = useCase.getTasks().values().stream().map(TaskPair::getTaskStringId).collect(Collectors.toSet()); - enabledRoles = new HashSet<>(useCase.getEnabledRoles()); - viewRoles = new HashSet<>(useCase.getViewRoles()); - viewUserRefs = new HashSet<>(useCase.getViewUserRefs()); - negativeViewRoles = new HashSet<>(useCase.getNegativeViewRoles()); - viewUsers = new HashSet<>(useCase.getViewUsers()); - negativeViewUsers = new HashSet<>(useCase.getNegativeViewUsers()); - tags = new HashMap<>(useCase.getTags()); + tags = new HashMap<>(useCase.getProperties()); dataSet = new HashMap<>(); } @@ -148,12 +139,12 @@ public void update(ElasticCase useCase) { title = useCase.getTitle(); taskIds = useCase.getTaskIds(); taskMongoIds = useCase.getTaskMongoIds(); - enabledRoles = useCase.getEnabledRoles(); - viewRoles = useCase.getViewRoles(); - viewUserRefs = useCase.getViewUserRefs(); - negativeViewRoles = useCase.getNegativeViewRoles(); - viewUsers = useCase.getViewUsers(); - negativeViewUsers = useCase.getNegativeViewUsers(); + viewProcessRoles = useCase.getViewProcessRoles(); + positiveViewProcessRoles = useCase.getPositiveViewProcessRoles(); + viewCaseRoles = useCase.getViewCaseRoles(); + negativeViewProcessRoles = useCase.getNegativeViewProcessRoles(); + positiveViewCaseRoles = useCase.getPositiveViewCaseRoles(); + negativeViewCaseRoles = useCase.getNegativeViewCaseRoles(); tags = useCase.getTags(); dataSet = useCase.getDataSet(); diff --git a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticPetriNet.java b/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticPetriNet.java index 48637e4c236..e301f898b43 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticPetriNet.java +++ b/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticPetriNet.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.version.Version; import lombok.AllArgsConstructor; import lombok.Data; @@ -50,13 +50,15 @@ public class ElasticPetriNet { @Field(type = FieldType.Date, format = DateFormat.date_hour_minute_second_millis) private LocalDateTime creationDate; - public ElasticPetriNet(PetriNet net) { + public ElasticPetriNet(Process net) { this.identifier = net.getIdentifier(); this.version = net.getVersion(); this.uriNodeId = net.getUriNodeId(); this.stringId = net.getStringId(); this.title = net.getTitle(); - this.initials = net.getInitials(); + if (net.getProperties() != null) { + this.initials = net.getProperties().get("initials"); + } this.creationDate = net.getCreationDate(); } diff --git a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticQueryConstants.java b/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticQueryConstants.java index 70d7f005f5e..7545a024e90 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticQueryConstants.java +++ b/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticQueryConstants.java @@ -2,7 +2,7 @@ public class ElasticQueryConstants { /** - * Should be replaced by user id in elastic query string queries + * Should be replaced by actor id in elastic query string queries */ - public static final String USER_ID_TEMPLATE = "<>"; + public static final String ACTOR_ID_TEMPLATE = "<>"; } diff --git a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticTask.java b/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticTask.java index f335ea784e6..ce7fe27d98e 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticTask.java +++ b/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticTask.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.netgrif.application.engine.workflow.domain.State; import com.netgrif.application.engine.workflow.domain.Task; import lombok.AllArgsConstructor; import lombok.Data; @@ -16,7 +17,6 @@ import java.time.LocalDateTime; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -46,6 +46,9 @@ public class ElasticTask { @Field(type = Keyword) private String transitionId; + @Field(type = Keyword) + private State state; + @Field(type = Keyword) private String title; //TODO: i18n @@ -62,7 +65,7 @@ public class ElasticTask { private int priority; - private String userId; + private String assigneeId; @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonDeserialize(using = LocalDateTimeDeserializer.class) @@ -70,25 +73,22 @@ public class ElasticTask { private LocalDateTime startDate; @Field(type = Keyword) - private String transactionId; + private Set viewProcessRoles; @Field(type = Keyword) - private Set roles; + private Set viewCaseRoles; @Field(type = Keyword) - private Set viewUserRefs; + private Set positiveViewProcessRoles; @Field(type = Keyword) - private Set viewRoles; + private Set negativeViewProcessRoles; @Field(type = Keyword) - private Set negativeViewRoles; + private Set positiveViewCaseRoles; @Field(type = Keyword) - private Set viewUsers; - - @Field(type = Keyword) - private Set negativeViewUsers; + private Set negativeViewCaseRoles; @Field(type = Keyword) private String icon; @@ -102,7 +102,7 @@ public class ElasticTask { @Field(type = Keyword) private String finishPolicy; - private Map tags; + private Map properties; public ElasticTask(Task task) { this.stringId = task.getStringId(); @@ -112,35 +112,32 @@ public ElasticTask(Task task) { this.transitionId = task.getTransitionId(); this.title = task.getTitle().getDefaultValue(); this.titleSortable = title; - this.caseTitle = task.getCaseTitle(); + this.state = task.getState(); +// TODO: release/8.0.0 +// this.caseTitle = task.getCaseTitle(); this.caseTitleSortable = this.caseTitle; - if (task.getPriority() != null) - this.priority = task.getPriority(); - this.userId = task.getUserId(); +// if (task.getPriority() != null) +// this.priority = task.getPriority(); + this.assigneeId = task.getAssigneeId(); this.startDate = task.getLastAssigned(); - this.roles = task.getRoles().keySet(); - this.viewRoles = new HashSet<>(task.getViewRoles()); - this.viewUserRefs = new HashSet<>(task.getViewUserRefs()); - this.negativeViewRoles = new HashSet<>(task.getNegativeViewRoles()); - this.viewUsers = new HashSet<>(task.getViewUsers()); - this.negativeViewUsers = new HashSet<>(task.getNegativeViewUsers()); - this.tags = new HashMap<>(task.getTags()); + this.properties = new HashMap<>(task.getProperties()); } public void update(ElasticTask task) { this.title = task.getTitle(); this.titleSortable = title; + this.state = task.getState(); this.caseTitle = task.getCaseTitle(); this.caseTitleSortable = this.caseTitle; this.priority = task.getPriority(); - this.userId = task.getUserId(); + this.assigneeId = task.getAssigneeId(); this.startDate = task.getStartDate(); - this.roles = task.getRoles(); - this.viewRoles = task.getViewRoles(); - this.viewUserRefs = task.getViewUserRefs(); - this.negativeViewRoles = task.getNegativeViewRoles(); - this.viewUsers = task.getViewUsers(); - this.negativeViewUsers = task.getNegativeViewUsers(); - this.tags = task.getTags(); + this.viewProcessRoles = task.getViewProcessRoles(); + this.positiveViewProcessRoles = task.getPositiveViewProcessRoles(); + this.viewCaseRoles = task.getViewCaseRoles(); + this.negativeViewProcessRoles = task.getNegativeViewProcessRoles(); + this.positiveViewCaseRoles = task.getPositiveViewCaseRoles(); + this.negativeViewCaseRoles = task.getNegativeViewCaseRoles(); + this.properties = task.getProperties(); } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticCaseRepository.java b/src/main/java/com/netgrif/application/engine/elastic/domain/repoitories/ElasticCaseRepository.java similarity index 77% rename from src/main/java/com/netgrif/application/engine/elastic/domain/ElasticCaseRepository.java rename to src/main/java/com/netgrif/application/engine/elastic/domain/repoitories/ElasticCaseRepository.java index ad760d40424..ce7482ae03f 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticCaseRepository.java +++ b/src/main/java/com/netgrif/application/engine/elastic/domain/repoitories/ElasticCaseRepository.java @@ -1,5 +1,6 @@ -package com.netgrif.application.engine.elastic.domain; +package com.netgrif.application.engine.elastic.domain.repoitories; +import com.netgrif.application.engine.elastic.domain.ElasticCase; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.stereotype.Repository; diff --git a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticPetriNetRepository.java b/src/main/java/com/netgrif/application/engine/elastic/domain/repoitories/ElasticPetriNetRepository.java similarity index 68% rename from src/main/java/com/netgrif/application/engine/elastic/domain/ElasticPetriNetRepository.java rename to src/main/java/com/netgrif/application/engine/elastic/domain/repoitories/ElasticPetriNetRepository.java index 023b877ccad..ca0ad9b2b46 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticPetriNetRepository.java +++ b/src/main/java/com/netgrif/application/engine/elastic/domain/repoitories/ElasticPetriNetRepository.java @@ -1,5 +1,6 @@ -package com.netgrif.application.engine.elastic.domain; +package com.netgrif.application.engine.elastic.domain.repoitories; +import com.netgrif.application.engine.elastic.domain.ElasticPetriNet; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.stereotype.Repository; @@ -13,4 +14,6 @@ public interface ElasticPetriNetRepository extends ElasticsearchRepository findAllByUriNodeId(String uriNodeId); void deleteAllByStringId(String id); + + List findAllByIdentifier(String identifier); } diff --git a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticTaskRepository.java b/src/main/java/com/netgrif/application/engine/elastic/domain/repoitories/ElasticTaskRepository.java similarity index 81% rename from src/main/java/com/netgrif/application/engine/elastic/domain/ElasticTaskRepository.java rename to src/main/java/com/netgrif/application/engine/elastic/domain/repoitories/ElasticTaskRepository.java index 85b08a06abb..18a0b55d709 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/domain/ElasticTaskRepository.java +++ b/src/main/java/com/netgrif/application/engine/elastic/domain/repoitories/ElasticTaskRepository.java @@ -1,5 +1,6 @@ -package com.netgrif.application.engine.elastic.domain; +package com.netgrif.application.engine.elastic.domain.repoitories; +import com.netgrif.application.engine.elastic.domain.ElasticTask; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.stereotype.Repository; diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java index 1194108b81d..33344307a8d 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.elastic.service; +import com.netgrif.application.engine.authorization.domain.permissions.CasePermission; import com.netgrif.application.engine.elastic.domain.DataField; import com.netgrif.application.engine.elastic.domain.ElasticCase; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseMappingService; @@ -8,6 +9,7 @@ import com.netgrif.application.engine.importer.model.DataType; import com.netgrif.application.engine.petrinet.domain.dataset.Field; import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.elastic.ElasticMappingUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -31,7 +33,10 @@ public ElasticCaseMappingService(@Autowired List transformDataField(String fieldId, Case useCase) { } return Optional.ofNullable(transformer.transform(caseField, netField)); } + + protected void populatePermissions(ElasticCase transformedCase, Case useCase) { + transformedCase.setViewProcessRoles(ElasticMappingUtils.filterRoleIdsByPermissionType( + useCase.getProcessRolePermissions(), CasePermission.VIEW)); + transformedCase.setPositiveViewProcessRoles(ElasticMappingUtils.filterRoleIdsByPermissionValue( + useCase.getProcessRolePermissions(), CasePermission.VIEW, true)); + transformedCase.setNegativeViewProcessRoles(ElasticMappingUtils.filterRoleIdsByPermissionValue( + useCase.getProcessRolePermissions(), CasePermission.VIEW, false)); + + transformedCase.setViewCaseRoles(ElasticMappingUtils.filterRoleIdsByPermissionType( + useCase.getCaseRolePermissions(), CasePermission.VIEW)); + transformedCase.setPositiveViewCaseRoles(ElasticMappingUtils.filterRoleIdsByPermissionValue( + useCase.getCaseRolePermissions(), CasePermission.VIEW, true)); + transformedCase.setNegativeViewCaseRoles(ElasticMappingUtils.filterRoleIdsByPermissionValue( + useCase.getCaseRolePermissions(), CasePermission.VIEW, false)); + } } diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseSearchService.java b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseSearchService.java new file mode 100644 index 00000000000..9a2526b408d --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseSearchService.java @@ -0,0 +1,83 @@ +package com.netgrif.application.engine.elastic.service; + +import com.netgrif.application.engine.configuration.properties.ElasticsearchProperties; +import com.netgrif.application.engine.elastic.domain.ElasticCase; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCasePrioritySearch; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseSearchService; +import com.netgrif.application.engine.elastic.service.query.ElasticCaseQueryBuilder; +import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; +import com.netgrif.application.engine.utils.FullPageRequest; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import lombok.extern.slf4j.Slf4j; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.springframework.context.annotation.Lazy; +import org.springframework.data.domain.*; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.elasticsearch.core.SearchHitSupport; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; +import org.springframework.stereotype.Service; + +import javax.annotation.Nullable; +import java.util.*; +import java.util.stream.Collectors; + +/** + * todo javadoc + * */ +@Slf4j +@Service +public class ElasticCaseSearchService extends ElasticSearchService implements IElasticCaseSearchService { + + private final IWorkflowService workflowService; + private final ElasticsearchRestTemplate template; + private final ElasticsearchProperties properties; + + public ElasticCaseSearchService(@Lazy IWorkflowService workflowService, ElasticsearchRestTemplate template, + ElasticsearchProperties properties, IElasticCasePrioritySearch elasticCasePrioritySearch) { + super(new ElasticCaseQueryBuilder(elasticCasePrioritySearch)); + this.workflowService = workflowService; + this.template = template; + this.properties = properties; + } + + @Override + public Page search(List requests, @Nullable String actorId, Pageable pageable, + Locale locale, Boolean isIntersection, @Nullable BoolQueryBuilder permissionQuery) { + if (requests == null) { + throw new IllegalArgumentException("Request can not be null!"); + } + + pageable = ((ElasticCaseQueryBuilder) queryBuilder).resolveUnmappedSortAttributes(pageable); + NativeSearchQuery query = buildQuery(requests, actorId, pageable, locale, isIntersection, permissionQuery); + List casePage; + long total; + if (query != null) { + SearchHits hits = template.search(query, ElasticCase.class, + IndexCoordinates.of(properties.getIndex().get("case"))); + Page indexedCases = (Page) SearchHitSupport.unwrapSearchHits(SearchHitSupport.searchPageFor(hits, + query.getPageable())); + casePage = workflowService.findAllById(indexedCases.get().map(ElasticCase::getStringId).collect(Collectors.toList())); + total = indexedCases.getTotalElements(); + } else { + casePage = Collections.emptyList(); + total = 0; + } + + return new PageImpl<>(casePage, pageable, total); + } + + @Override + public long count(List requests, @Nullable String actorId, Locale locale, + Boolean isIntersection, @Nullable BoolQueryBuilder permissionQuery) { + if (requests == null) { + throw new IllegalArgumentException("Request can not be null!"); + } + + NativeSearchQuery query = buildQuery(requests, actorId, new FullPageRequest(), locale, isIntersection, permissionQuery); + + return query != null ? template.count(query, ElasticCase.class) : 0; + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseService.java b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseService.java index bd7fc69ac29..d8316a2db8b 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseService.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseService.java @@ -1,491 +1,91 @@ package com.netgrif.application.engine.elastic.service; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.configuration.properties.ElasticsearchProperties; import com.netgrif.application.engine.elastic.domain.ElasticCase; -import com.netgrif.application.engine.elastic.domain.ElasticCaseRepository; -import com.netgrif.application.engine.elastic.domain.ElasticQueryConstants; +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticCaseRepository; import com.netgrif.application.engine.elastic.service.executors.Executor; -import com.netgrif.application.engine.elastic.service.interfaces.IElasticCasePrioritySearch; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseMappingService; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseSearchService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; +import com.netgrif.application.engine.elastic.service.query.ElasticPermissionQueryBuilder; import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; -import com.netgrif.application.engine.petrinet.domain.PetriNetSearch; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference; -import com.netgrif.application.engine.utils.FullPageRequest; import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.index.query.QueryBuilder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Lazy; import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.data.domain.*; -import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; -import org.springframework.data.elasticsearch.core.SearchHitSupport; -import org.springframework.data.elasticsearch.core.SearchHits; -import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; -import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; -import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; -import org.springframework.data.elasticsearch.core.query.Order; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import java.util.*; -import java.util.function.BinaryOperator; -import java.util.stream.Collectors; - -import static org.elasticsearch.index.query.QueryBuilders.*; +import java.util.List; +import java.util.Locale; +/** + * todo javadoc + * */ @Slf4j @Service -public class ElasticCaseService extends ElasticViewPermissionService implements IElasticCaseService { - - protected ElasticCaseRepository repository; - - protected IWorkflowService workflowService; - - @Value("${spring.data.elasticsearch.index.case}") - protected String caseIndex; - - @Autowired - protected ElasticsearchRestTemplate template; - - protected Executor executors; - - @Autowired - protected ElasticsearchProperties elasticsearchProperties; - - @Autowired - protected IPetriNetService petriNetService; - - @Autowired - protected IElasticCasePrioritySearch iElasticCasePrioritySearch; - - @Autowired - public ElasticCaseService(ElasticCaseRepository repository, ElasticsearchRestTemplate template, Executor executors) { - this.repository = repository; - this.template = template; - this.executors = executors; - } - - @Autowired - @Lazy - public void setWorkflowService(IWorkflowService workflowService) { - this.workflowService = workflowService; - } +@RequiredArgsConstructor +public class ElasticCaseService implements IElasticCaseService { - @Override - public void remove(String caseId) { - executors.execute(caseId, () -> { - repository.deleteAllByStringId(caseId); - log.info("[{}]: Case \"{}\" deleted", caseId, caseId); - }); - } - - @Override - public void removeByPetriNetId(String processId) { - executors.execute(processId, () -> { - repository.deleteAllByProcessId(processId); - log.info("[{}]: All cases of Petri Net with id \"{}\" deleted", processId, processId); - }); - } + private final ElasticCaseRepository repository; + private final Executor executors; + private final IElasticCaseMappingService mappingService; + private final IElasticCaseSearchService searchService; + private final ElasticPermissionQueryBuilder permissionQueryBuilder; @Override - public void index(ElasticCase useCase) { + public void index(Case useCase) { executors.execute(useCase.getStringId(), () -> { + ElasticCase elasticCase = mappingService.transform(useCase); try { - ElasticCase elasticCase = repository.findByStringId(useCase.getStringId()); - if (elasticCase == null) { - repository.save(useCase); - } else { - elasticCase.update(useCase); + ElasticCase savedCase = repository.findByStringId(useCase.getStringId()); + if (savedCase == null) { repository.save(elasticCase); + } else { + savedCase.update(elasticCase); + repository.save(savedCase); } } catch (InvalidDataAccessApiUsageException ignored) { log.debug("[{}]: Case \"{}\" has duplicates, will be reindexed", useCase.getStringId(), useCase.getTitle()); repository.deleteAllByStringId(useCase.getStringId()); - repository.save(useCase); + repository.save(elasticCase); } log.debug("[{}]: Case \"{}\" indexed", useCase.getStringId(), useCase.getTitle()); }); } @Override - public void indexNow(ElasticCase useCase) { + public void indexNow(Case useCase) { index(useCase); } @Override - public Page search(List requests, LoggedUser user, Pageable pageable, Locale locale, Boolean isIntersection) { - if (requests == null) { - throw new IllegalArgumentException("Request can not be null!"); - } - - LoggedUser loggedOrImpersonated = user.getSelfOrImpersonated(); - pageable = resolveUnmappedSortAttributes(pageable); - NativeSearchQuery query = buildQuery(requests, loggedOrImpersonated, pageable, locale, isIntersection); - List casePage; - long total; - if (query != null) { - SearchHits hits = template.search(query, ElasticCase.class, IndexCoordinates.of(caseIndex)); - Page indexedCases = (Page) SearchHitSupport.unwrapSearchHits(SearchHitSupport.searchPageFor(hits, query.getPageable())); - casePage = workflowService.findAllById(indexedCases.get().map(ElasticCase::getStringId).collect(Collectors.toList())); - total = indexedCases.getTotalElements(); - } else { - casePage = Collections.emptyList(); - total = 0; - } - - return new PageImpl<>(casePage, pageable, total); + public Page search(List requests, String actorId, Pageable pageable, Locale locale, + Boolean isIntersection) { + BoolQueryBuilder permissionQuery = permissionQueryBuilder.buildSingleQuery(actorId); + return searchService.search(requests, actorId, pageable, locale, isIntersection, permissionQuery); } @Override - public long count(List requests, LoggedUser user, Locale locale, Boolean isIntersection) { - if (requests == null) { - throw new IllegalArgumentException("Request can not be null!"); - } - - LoggedUser loggedOrImpersonated = user.getSelfOrImpersonated(); - NativeSearchQuery query = buildQuery(requests, loggedOrImpersonated, new FullPageRequest(), locale, isIntersection); - if (query != null) { - return template.count(query, ElasticCase.class); - } else { - return 0; - } - } - - public String findUriNodeId(Case aCase) { - if (aCase == null) { - return null; - } - ElasticCase elasticCase = repository.findByStringId(aCase.getStringId()); - if (elasticCase == null) { - log.warn("[{}] Case with id [{}] is not indexed.", aCase.getStringId(), aCase.getStringId()); - return null; - } - - return elasticCase.getUriNodeId(); - } - - protected NativeSearchQuery buildQuery(List requests, LoggedUser user, Pageable pageable, Locale locale, Boolean isIntersection) { - List singleQueries = requests.stream().map(request -> buildSingleQuery(request, user, locale)).collect(Collectors.toList()); - - if (isIntersection && !singleQueries.stream().allMatch(Objects::nonNull)) { - // one of the queries evaluates to empty set => the entire result is an empty set - return null; - } else if (!isIntersection) { - singleQueries = singleQueries.stream().filter(Objects::nonNull).collect(Collectors.toList()); - if (singleQueries.size() == 0) { - // all queries result in an empty set => the entire result is an empty set - return null; - } - } - - BinaryOperator reductionOperator = isIntersection ? BoolQueryBuilder::must : BoolQueryBuilder::should; - BoolQueryBuilder query = singleQueries.stream().reduce(new BoolQueryBuilder(), reductionOperator); - - NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder(); - return builder - .withQuery(query) - .withPageable(pageable) - .build(); - } - - protected BoolQueryBuilder buildSingleQuery(CaseSearchRequest request, LoggedUser user, Locale locale) { - BoolQueryBuilder query = boolQuery(); - - buildViewPermissionQuery(query, user); - buildPetriNetQuery(request, user, query); - buildAuthorQuery(request, query); - buildTaskQuery(request, query); - buildRoleQuery(request, query); - buildDataQuery(request, query); - buildFullTextQuery(request, query); - buildStringQuery(request, query, user); - buildCaseIdQuery(request, query); - buildUriNodeIdQuery(request, query); - buildTagsQuery(request, query); - boolean resultAlwaysEmpty = buildGroupQuery(request, user, locale, query); - - // TODO: filtered query https://stackoverflow.com/questions/28116404/filtered-query-using-nativesearchquerybuilder-in-spring-data-elasticsearch - - if (resultAlwaysEmpty) - return null; - else - return query; - } - - protected void buildPetriNetQuery(CaseSearchRequest request, LoggedUser user, BoolQueryBuilder query) { - if (request.process == null || request.process.isEmpty()) { - return; - } - - BoolQueryBuilder petriNetQuery = boolQuery(); - - for (CaseSearchRequest.PetriNet process : request.process) { - if (process.identifier != null) { - petriNetQuery.should(termQuery("processIdentifier", process.identifier)); - } - if (process.processId != null) { - petriNetQuery.should(termQuery("processId", process.processId)); - } - } - - query.filter(petriNetQuery); - } - - /** - *
-     * {
-     *     "author": {
-     *         "email": "user@customer.com"
-     *     }
-     * }
-     * 

- *

- * Cases with author with (id 1 AND email "user@customer.com") OR (id 2) - *

-     * {
-     *     "author": [{
-     *         "id": 1
-     *         "email": "user@customer.com"
-     *     }, {
-     *         "id": 2
-     *     }
-     *     ]
-     * }
-     * 

- */ - protected void buildAuthorQuery(CaseSearchRequest request, BoolQueryBuilder query) { - if (request.author == null || request.author.isEmpty()) { - return; - } - - BoolQueryBuilder authorsQuery = boolQuery(); - for (CaseSearchRequest.Author author : request.author) { - BoolQueryBuilder authorQuery = boolQuery(); - if (author.email != null) { - authorQuery.must(termQuery("authorEmail", author.email)); - } - if (author.id != null) { - authorQuery.must(matchQuery("author", author.id)); - } - if (author.name != null) { - authorQuery.must(termQuery("authorName", author.name)); - } - authorsQuery.should(authorQuery); - } - - query.filter(authorsQuery); - } - - /** - * Cases with tasks with import Id "nova_uloha" - *
-     * {
-     *     "transition": "nova_uloha"
-     * }
-     * 
- *

- * Cases with tasks with import Id "nova_uloha" OR "kontrola" - *

-     * {
-     *     "transition": [
-     *         "nova_uloha",
-     *         "kontrola"
-     *     ]
-     * }
-     * 
- */ - protected void buildTaskQuery(CaseSearchRequest request, BoolQueryBuilder query) { - if (request.transition == null || request.transition.isEmpty()) { - return; - } - - BoolQueryBuilder taskQuery = boolQuery(); - for (String taskImportId : request.transition) { - taskQuery.should(termQuery("taskIds", taskImportId)); - } - - query.filter(taskQuery); - } - - /** - * Cases with active role "5cb07b6ff05be15f0b972c36" - *
-     * {
-     *     "role": "5cb07b6ff05be15f0b972c36"
-     * }
-     * 
- *

- * Cases with active role "5cb07b6ff05be15f0b972c36" OR "5cb07b6ff05be15f0b972c31" - *

-     * {
-     *     "role" [
-     *         "5cb07b6ff05be15f0b972c36",
-     *         "5cb07b6ff05be15f0b972c31"
-     *     ]
-     * }
-     * 
- */ - protected void buildRoleQuery(CaseSearchRequest request, BoolQueryBuilder query) { - if (request.role == null || request.role.isEmpty()) { - return; - } - - BoolQueryBuilder roleQuery = boolQuery(); - for (String roleId : request.role) { - roleQuery.should(termQuery("enabledRoles", roleId)); - } - - query.filter(roleQuery); - } - - /** - * Cases where "text_field" has value EXACTLY "text" AND "number_field" has value EXACTLY "125".
- *
-     * {
-     *     "data": {
-     *         "text_field": "text",
-     *         "number_field": "125"
-     *     }
-     * }
-     * 
- */ - protected void buildDataQuery(CaseSearchRequest request, BoolQueryBuilder query) { - if (request.data == null || request.data.isEmpty()) { - return; - } - - BoolQueryBuilder dataQuery = boolQuery(); - for (Map.Entry field : request.data.entrySet()) { - if (field.getKey().contains(".")) - dataQuery.must(termQuery("dataSet." + field.getKey(), field.getValue())); - else - dataQuery.must(termQuery("dataSet." + field.getKey() + ".fulltextValue.keyword", field.getValue())); - } - - query.filter(dataQuery); - } - - protected void buildTagsQuery(CaseSearchRequest request, BoolQueryBuilder query) { - if (request.tags == null || request.tags.isEmpty()) { - return; - } - - BoolQueryBuilder tagsQuery = boolQuery(); - for (Map.Entry field : request.tags.entrySet()) { - tagsQuery.must(termQuery("tags." + field.getKey(), field.getValue())); - } - - query.filter(tagsQuery); - } - - protected void buildFullTextQuery(CaseSearchRequest request, BoolQueryBuilder query) { - if (request.fullText == null || request.fullText.isEmpty()) { - return; - } - - // TODO: improvement? wildcard does not scale good - //String searchText = elasticsearchProperties.isAnalyzerEnabled() ? request.fullText : "*" + request.fullText + "*"; - String searchText = "*" + request.fullText + "*"; - QueryBuilder fullTextQuery = queryStringQuery(searchText).fields(iElasticCasePrioritySearch.fullTextFields()); - query.must(fullTextQuery); + public long count(List requests, String actorId, Locale locale, Boolean isIntersection) { + BoolQueryBuilder permissionQuery = permissionQueryBuilder.buildSingleQuery(actorId); + return searchService.count(requests, actorId, locale, isIntersection, permissionQuery); } - /** - * See Query String Query - */ - protected void buildStringQuery(CaseSearchRequest request, BoolQueryBuilder query, LoggedUser user) { - if (request.query == null || request.query.isEmpty()) { - return; - } - - String populatedQuery = request.query.replaceAll(ElasticQueryConstants.USER_ID_TEMPLATE, user.getId().toString()); - - query.must(queryStringQuery(populatedQuery).allowLeadingWildcard(true).analyzeWildcard(true)); - } - - /** - * Case with stringId "5cb07b6ff05be15f0b972c36" - *
-     * {
-     *     "stringId": "5cb07b6ff05be15f0b972c36"
-     * }
-     * 
- *

- * Cases with stringId "5cb07b6ff05be15f0b972c36" OR "5cb07b6ff05be15f0b972c31" - *

-     * {
-     *     "stringId" [
-     *         "5cb07b6ff05be15f0b972c36",
-     *         "5cb07b6ff05be15f0b972c31"
-     *     ]
-     * }
-     * 
- */ - protected void buildCaseIdQuery(CaseSearchRequest request, BoolQueryBuilder query) { - if (request.stringId == null || request.stringId.isEmpty()) { - return; - } - - BoolQueryBuilder caseIdQuery = boolQuery(); - request.stringId.forEach(caseId -> caseIdQuery.should(termQuery("stringId", caseId))); - query.filter(caseIdQuery); - } - - protected void buildUriNodeIdQuery(CaseSearchRequest request, BoolQueryBuilder query) { - if (request.uriNodeId == null || request.uriNodeId.isEmpty()) { - return; - } - - BoolQueryBuilder caseIdQuery = boolQuery(); - caseIdQuery.should(termQuery("uriNodeId", request.uriNodeId)); - query.filter(caseIdQuery); - } - - /** - * Cases that are instances of processes of group "5cb07b6ff05be15f0b972c36" - *
-     * {
-     *     "group": "5cb07b6ff05be15f0b972c36"
-     * }
-     * 
- *

- * Cases that are instances of processes of group "5cb07b6ff05be15f0b972c36" OR "5cb07b6ff05be15f0b972c31" - *

-     * {
-     *     "group" [
-     *         "5cb07b6ff05be15f0b972c36",
-     *         "5cb07b6ff05be15f0b972c31"
-     *     ]
-     * }
-     * 
- */ - protected boolean buildGroupQuery(CaseSearchRequest request, LoggedUser user, Locale locale, BoolQueryBuilder query) { - if (request.group == null || request.group.isEmpty()) { - return false; - } - - PetriNetSearch processQuery = new PetriNetSearch(); - processQuery.setGroup(request.group); - List groupProcesses = this.petriNetService.search(processQuery, user, new FullPageRequest(), locale).getContent(); - if (groupProcesses.size() == 0) - return true; - - BoolQueryBuilder groupQuery = boolQuery(); - groupProcesses.stream().map(PetriNetReference::getIdentifier) - .map(netIdentifier -> termQuery("processIdentifier", netIdentifier)) - .forEach(groupQuery::should); - query.filter(groupQuery); - return false; + @Override + public void remove(String caseId) { + executors.execute(caseId, () -> { + repository.deleteAllByStringId(caseId); + log.info("[{}]: Case \"{}\" deleted", caseId, caseId); + }); } - protected Pageable resolveUnmappedSortAttributes(Pageable pageable) { - List modifiedOrders = new ArrayList<>(); - pageable.getSort().iterator().forEachRemaining(order -> modifiedOrders.add(new Order(order.getDirection(), order.getProperty()).withUnmappedType("keyword"))); - return PageRequest.of(pageable.getPageNumber(), pageable.getPageSize()).withSort(Sort.by(modifiedOrders)); + @Override + public void removeByPetriNetId(String processId) { + executors.execute(processId, () -> { + repository.deleteAllByProcessId(processId); + log.info("[{}]: All cases of Petri Net with id \"{}\" deleted", processId, processId); + }); } -} \ No newline at end of file +} diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetMappingService.java b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetMappingService.java index f6173f74903..52d7fc64918 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetMappingService.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetMappingService.java @@ -2,14 +2,14 @@ import com.netgrif.application.engine.elastic.domain.ElasticPetriNet; import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetMappingService; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import org.springframework.stereotype.Service; @Service public class ElasticPetriNetMappingService implements IElasticPetriNetMappingService { @Override - public ElasticPetriNet transform(PetriNet net) { + public ElasticPetriNet transform(Process net) { return new ElasticPetriNet(net); } } diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java index 3777f1ddb86..fe8803937e3 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java @@ -1,11 +1,12 @@ package com.netgrif.application.engine.elastic.service; import com.netgrif.application.engine.elastic.domain.ElasticPetriNet; -import com.netgrif.application.engine.elastic.domain.ElasticPetriNetRepository; +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticPetriNetRepository; import com.netgrif.application.engine.elastic.service.executors.Executor; import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetService; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; @@ -15,8 +16,9 @@ import java.util.List; import java.util.stream.Collectors; -@Service @Slf4j +@Service +@RequiredArgsConstructor public class ElasticPetriNetService implements IElasticPetriNetService { private final ElasticPetriNetRepository repository; @@ -25,11 +27,6 @@ public class ElasticPetriNetService implements IElasticPetriNetService { private IPetriNetService petriNetService; - public ElasticPetriNetService(ElasticPetriNetRepository repository, Executor executors) { - this.repository = repository; - this.executors = executors; - } - @Lazy @Autowired public void setPetriNetService(IPetriNetService petriNetService) { @@ -47,12 +44,12 @@ public void index(ElasticPetriNet net) { elasticPetriNet.update(net); repository.save(elasticPetriNet); } - log.debug("[" + net.getStringId() + "]: PetriNet \"" + net.getTitle() + "\" indexed"); + log.debug("[{}]: PetriNet \"{}\" indexed", net.getStringId(), net.getTitle()); } catch (InvalidDataAccessApiUsageException ignored) { - log.debug("[" + net.getStringId() + "]: PetriNet \"" + net.getTitle() + "\" has duplicates, will be reindexed"); + log.debug("[{}]: PetriNet \"{}\" has duplicates, will be reindexed", net.getStringId(), net.getTitle()); repository.deleteAllByStringId(net.getStringId()); repository.save(net); - log.debug("[" + net.getStringId() + "]: PetriNet \"" + net.getTitle() + "\" indexed"); + log.debug("[{}]: PetriNet \"{}\" indexed", net.getStringId(), net.getTitle()); } }); } @@ -66,18 +63,18 @@ public void indexNow(ElasticPetriNet net) { public void remove(String id) { executors.execute(id, () -> { repository.deleteAllByStringId(id); - log.info("[" + id + "]: PetriNet \"" + id + "\" deleted"); + log.info("[{}]: PetriNet \"{}\" deleted", id, id); }); } @Override - public String findUriNodeId(PetriNet net) { + public String findUriNodeId(Process net) { if (net == null) { return null; } ElasticPetriNet elasticPetriNet = repository.findByStringId(net.getStringId()); if (elasticPetriNet == null) { - log.warn("[" + net.getStringId() + "] PetriNet with id [" + net.getStringId() + "] is not indexed."); + log.warn("[{}] PetriNet with id [{}] is not indexed.", net.getStringId(), net.getStringId()); return null; } @@ -85,8 +82,14 @@ public String findUriNodeId(PetriNet net) { } @Override - public List findAllByUriNodeId(String uriNodeId) { + public List findAllByUriNodeId(String uriNodeId) { List elasticPetriNets = repository.findAllByUriNodeId(uriNodeId); return petriNetService.findAllById(elasticPetriNets.stream().map(ElasticPetriNet::getStringId).collect(Collectors.toList())); } + + @Override + public List findAllByIdentifier(String identifier) { + List elasticProcesses = repository.findAllByIdentifier(identifier); + return petriNetService.findAllById(elasticProcesses.stream().map(ElasticPetriNet::getStringId).collect(Collectors.toList())); + } } diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticSearchService.java b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticSearchService.java new file mode 100644 index 00000000000..e434ce0bb13 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticSearchService.java @@ -0,0 +1,50 @@ +package com.netgrif.application.engine.elastic.service; + +import com.netgrif.application.engine.elastic.service.query.ElasticQueryBuilder; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.stream.Collectors; + +public abstract class ElasticSearchService { + + protected final ElasticQueryBuilder queryBuilder; + + protected ElasticSearchService(ElasticQueryBuilder queryBuilder) { + this.queryBuilder = queryBuilder; + } + + protected NativeSearchQuery buildQuery(List requests, @Nullable String actorId, Pageable pageable, + Locale locale, Boolean isIntersection, @Nullable BoolQueryBuilder permissionQuery) { + List singleQueries = requests.stream() + .map(request -> queryBuilder.buildSingleQuery(request, locale, actorId, permissionQuery)) + .collect(Collectors.toList()); + + if (isIntersection && !singleQueries.stream().allMatch(Objects::nonNull)) { + // one of the queries evaluates to empty set => the entire result is an empty set + return null; + } else if (!isIntersection) { + singleQueries = singleQueries.stream().filter(Objects::nonNull).collect(Collectors.toList()); + if (singleQueries.isEmpty()) { + // all queries result in an empty set => the entire result is an empty set + return null; + } + } + + BinaryOperator reductionOperator = isIntersection ? BoolQueryBuilder::must : BoolQueryBuilder::should; + BoolQueryBuilder query = singleQueries.stream().reduce(new BoolQueryBuilder(), reductionOperator); + + NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder(); + return builder + .withQuery(query) + .withPageable(pageable) + .build(); + } +} diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskMappingService.java b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskMappingService.java index 721987ab61c..1152f239d8f 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskMappingService.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskMappingService.java @@ -1,14 +1,39 @@ package com.netgrif.application.engine.elastic.service; +import com.netgrif.application.engine.authorization.domain.permissions.TaskPermission; +import com.netgrif.application.engine.elastic.ElasticMappingUtils; import com.netgrif.application.engine.elastic.domain.ElasticTask; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskMappingService; +import com.netgrif.application.engine.workflow.domain.State; import com.netgrif.application.engine.workflow.domain.Task; import org.springframework.stereotype.Service; @Service public class ElasticTaskMappingService implements IElasticTaskMappingService { + @Override public ElasticTask transform(Task task) { - return new ElasticTask(task); + ElasticTask transformedTask = new ElasticTask(task); + + TaskPermission permission = task.getState() == State.ENABLED ? TaskPermission.VIEW : TaskPermission.VIEW_DISABLED; + this.populatePermissions(transformedTask, task, permission); + + return transformedTask; + } + + protected void populatePermissions(ElasticTask transformedTask, Task task, TaskPermission permission) { + transformedTask.setViewProcessRoles(ElasticMappingUtils.filterRoleIdsByPermissionType( + task.getProcessRolePermissions(), permission)); + transformedTask.setPositiveViewProcessRoles(ElasticMappingUtils.filterRoleIdsByPermissionValue( + task.getProcessRolePermissions(), permission, true)); + transformedTask.setNegativeViewProcessRoles(ElasticMappingUtils.filterRoleIdsByPermissionValue( + task.getProcessRolePermissions(), permission, false)); + + transformedTask.setViewCaseRoles(ElasticMappingUtils.filterRoleIdsByPermissionType( + task.getCaseRolePermissions(), permission)); + transformedTask.setPositiveViewCaseRoles(ElasticMappingUtils.filterRoleIdsByPermissionValue( + task.getCaseRolePermissions(), permission, true)); + transformedTask.setNegativeViewCaseRoles(ElasticMappingUtils.filterRoleIdsByPermissionValue( + task.getCaseRolePermissions(), permission, false)); } } diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskQueueManager.java b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskQueueManager.java index 3c4e89ac835..19ff3ff3e6d 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskQueueManager.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskQueueManager.java @@ -3,7 +3,7 @@ import com.netgrif.application.engine.elastic.domain.ElasticJob; import com.netgrif.application.engine.elastic.domain.ElasticTask; import com.netgrif.application.engine.elastic.domain.ElasticTaskJob; -import com.netgrif.application.engine.elastic.domain.ElasticTaskRepository; +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticTaskRepository; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.dao.InvalidDataAccessApiUsageException; diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskSearchService.java b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskSearchService.java new file mode 100644 index 00000000000..6cc3a71d475 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskSearchService.java @@ -0,0 +1,77 @@ +package com.netgrif.application.engine.elastic.service; + +import com.netgrif.application.engine.configuration.properties.ElasticsearchProperties; +import com.netgrif.application.engine.elastic.domain.*; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskSearchService; +import com.netgrif.application.engine.elastic.service.query.ElasticTaskQueryBuilder; +import com.netgrif.application.engine.elastic.web.requestbodies.ElasticTaskSearchRequest; +import com.netgrif.application.engine.utils.FullPageRequest; +import com.netgrif.application.engine.workflow.domain.Task; +import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; +import lombok.extern.slf4j.Slf4j; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.elasticsearch.core.SearchHitSupport; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; +import org.springframework.stereotype.Service; + +import javax.annotation.Nullable; +import java.util.*; +import java.util.stream.Collectors; + +/** + * todo javadoc + * */ +@Slf4j +@Service +public class ElasticTaskSearchService extends ElasticSearchService implements IElasticTaskSearchService { + + private final ITaskService taskService; + private final ElasticsearchRestTemplate template; + private final ElasticsearchProperties properties; + private final ElasticsearchRestTemplate elasticsearchTemplate; + + @Autowired + public ElasticTaskSearchService(@Lazy ITaskService taskService, ElasticsearchRestTemplate template, + ElasticsearchProperties properties, ElasticsearchRestTemplate elasticsearchTemplate) { + super(new ElasticTaskQueryBuilder()); + this.taskService = taskService; + this.template = template; + this.properties = properties; + this.elasticsearchTemplate = elasticsearchTemplate; + } + + @Override + public Page search(List requests, @Nullable String actorId, Pageable pageable, + Locale locale, Boolean isIntersection, @Nullable BoolQueryBuilder permissionQuery) { + NativeSearchQuery query = buildQuery(requests, actorId, pageable, locale, isIntersection, permissionQuery); + List taskPage; + long total; + if (query != null) { + SearchHits hits = elasticsearchTemplate.search(query, ElasticTask.class, IndexCoordinates.of(properties.getIndex().get("task"))); + Page indexedTasks = (Page) SearchHitSupport.unwrapSearchHits(SearchHitSupport.searchPageFor(hits, query.getPageable())); + taskPage = taskService.findAllById(indexedTasks.get().map(ElasticTask::getStringId).collect(Collectors.toList())); + total = indexedTasks.getTotalElements(); + } else { + taskPage = Collections.emptyList(); + total = 0; + } + + return new PageImpl<>(taskPage, pageable, total); + } + + @Override + public long count(List requests, @Nullable String actorId, Locale locale, + Boolean isIntersection, @Nullable BoolQueryBuilder permissionQuery) { + NativeSearchQuery query = buildQuery(requests, actorId, new FullPageRequest(), locale, isIntersection, permissionQuery); + + return query != null ? template.count(query, ElasticTask.class) : 0; + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskService.java b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskService.java index 23bf0c1470c..c05fc810a9c 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskService.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskService.java @@ -1,88 +1,36 @@ package com.netgrif.application.engine.elastic.service; -import com.google.common.collect.ImmutableMap; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.elastic.domain.*; +import com.netgrif.application.engine.elastic.domain.ElasticJob; +import com.netgrif.application.engine.elastic.domain.ElasticTask; +import com.netgrif.application.engine.elastic.domain.ElasticTaskJob; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskSearchService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; +import com.netgrif.application.engine.elastic.service.query.ElasticPermissionQueryBuilder; +import com.netgrif.application.engine.elastic.service.query.ElasticTaskQueryBuilder; import com.netgrif.application.engine.elastic.web.requestbodies.ElasticTaskSearchRequest; -import com.netgrif.application.engine.petrinet.domain.PetriNetSearch; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference; -import com.netgrif.application.engine.utils.FullPageRequest; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; -import com.netgrif.application.engine.workflow.web.requestbodies.TaskSearchRequest; -import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.PetriNet; -import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.TaskSearchCaseRequest; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryStringQueryBuilder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Lazy; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; -import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; -import org.springframework.data.elasticsearch.core.SearchHitSupport; -import org.springframework.data.elasticsearch.core.SearchHits; -import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; -import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; -import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; -import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.List; +import java.util.Locale; +import java.util.Map; import java.util.concurrent.Future; -import java.util.function.BinaryOperator; -import java.util.stream.Collectors; - -import static org.elasticsearch.index.query.QueryBuilders.*; @Slf4j @Service -public class ElasticTaskService extends ElasticViewPermissionService implements IElasticTaskService { - - protected ElasticTaskRepository repository; - protected ITaskService taskService; - protected ElasticsearchRestTemplate template; - protected ExecutorService executor = Executors.newSingleThreadExecutor(); - - // TODO: release/8.0.0 properties - @Value("${spring.data.elasticsearch.index.task}") - protected String taskIndex; - - @Autowired - protected ElasticsearchRestTemplate elasticsearchTemplate; - - @Autowired - protected IPetriNetService petriNetService; - - protected Map fullTextFieldMap = ImmutableMap.of( - "title", 1f, - "caseTitle", 1f - ); +@RequiredArgsConstructor +public class ElasticTaskService implements IElasticTaskService { - protected Map caseTitledMap = ImmutableMap.of( - "caseTitle", 1f - ); - - @Autowired - private ElasticTaskQueueManager elasticTaskQueueManager; - - @Autowired - public ElasticTaskService(ElasticsearchRestTemplate template) { - this.template = template; - } - - @Autowired - @Lazy - public void setTaskService(ITaskService taskService) { - this.taskService = taskService; - } + private final IElasticTaskSearchService searchService; + private final ElasticTaskQueueManager elasticTaskQueueManager; + private final ElasticTaskQueryBuilder queryBuilder; + private final ElasticPermissionQueryBuilder permissionQueryBuilder; /** * See {@link QueryStringQueryBuilder#fields(Map)} @@ -91,19 +39,7 @@ public void setTaskService(ITaskService taskService) { */ @Override public Map fullTextFields() { - return fullTextFieldMap; - } - - @Override - public void remove(String taskId) { - ElasticTask task = new ElasticTask(); - task.setTaskId(taskId); - elasticTaskQueueManager.scheduleOperation(new ElasticTaskJob(ElasticJob.REMOVE, task)); - } - - @Override - public void removeByPetriNetId(String petriNetId) { - elasticTaskQueueManager.removeTasksByProcess(petriNetId); + return queryBuilder.fullTextFields(); } @Override @@ -111,7 +47,6 @@ public Future scheduleTaskIndexing(ElasticTask task) { return elasticTaskQueueManager.scheduleOperation(new ElasticTaskJob(ElasticJob.INDEX, task)); } - @Async @Override public void index(ElasticTask task) { elasticTaskQueueManager.scheduleOperation(new ElasticTaskJob(ElasticJob.INDEX, task)); @@ -123,321 +58,27 @@ public void indexNow(ElasticTask task) { } @Override - public Page search(List requests, LoggedUser user, Pageable pageable, Locale locale, Boolean isIntersection) { - NativeSearchQuery query = buildQuery(requests, user.getSelfOrImpersonated(), pageable, locale, isIntersection); - List taskPage; - long total; - if (query != null) { - SearchHits hits = elasticsearchTemplate.search(query, ElasticTask.class, IndexCoordinates.of(taskIndex)); - Page indexedTasks = (Page) SearchHitSupport.unwrapSearchHits(SearchHitSupport.searchPageFor(hits, query.getPageable())); - taskPage = taskService.findAllById(indexedTasks.get().map(ElasticTask::getStringId).collect(Collectors.toList())); - total = indexedTasks.getTotalElements(); - } else { - taskPage = Collections.emptyList(); - total = 0; - } - - return new PageImpl<>(taskPage, pageable, total); + public Page search(List requests, String actorId, Pageable pageable, + Locale locale, Boolean isIntersection) { + BoolQueryBuilder permissionQuery = permissionQueryBuilder.buildSingleQuery(actorId); + return searchService.search(requests, actorId, pageable, locale, isIntersection, permissionQuery); } @Override - public long count(List requests, LoggedUser user, Locale locale, Boolean isIntersection) { - NativeSearchQuery query = buildQuery(requests, user.getSelfOrImpersonated(), new FullPageRequest(), locale, isIntersection); - if (query != null) { - return template.count(query, ElasticTask.class); - } else { - return 0; - } - } - - protected NativeSearchQuery buildQuery(List requests, LoggedUser user, Pageable pageable, Locale locale, Boolean isIntersection) { - List singleQueries = requests.stream().map(request -> buildSingleQuery(request, user, locale)).collect(Collectors.toList()); - - if (isIntersection && !singleQueries.stream().allMatch(Objects::nonNull)) { - // one of the queries evaluates to empty set => the entire result is an empty set - return null; - } else if (!isIntersection) { - singleQueries = singleQueries.stream().filter(Objects::nonNull).collect(Collectors.toList()); - if (singleQueries.size() == 0) { - // all queries result in an empty set => the entire result is an empty set - return null; - } - } - - BinaryOperator reductionOperator = isIntersection ? BoolQueryBuilder::must : BoolQueryBuilder::should; - BoolQueryBuilder query = singleQueries.stream().reduce(new BoolQueryBuilder(), reductionOperator); - - NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder(); - return builder - .withQuery(query) - .withPageable(pageable) - .build(); - } - - protected BoolQueryBuilder buildSingleQuery(ElasticTaskSearchRequest request, LoggedUser user, Locale locale) { - if (request == null) { - throw new IllegalArgumentException("Request can not be null!"); - } - addRolesQueryConstraint(request, user); - - BoolQueryBuilder query = boolQuery(); - buildViewPermissionQuery(query, user); - buildCaseQuery(request, query); - buildTitleQuery(request, query); - buildUserQuery(request, query); - buildProcessQuery(request, query); - buildFullTextQuery(request, query); - buildTransitionQuery(request, query); - buildTagsQuery(request, query); - buildStringQuery(request, query, user); - boolean resultAlwaysEmpty = buildGroupQuery(request, user, locale, query); - - if (resultAlwaysEmpty) - return null; - else - return query; - } - - protected void addRolesQueryConstraint(ElasticTaskSearchRequest request, LoggedUser user) { - if (request.role != null && !request.role.isEmpty()) { - Set roles = new HashSet<>(request.role); - roles.addAll(user.getProcessRoles()); - request.role = new ArrayList<>(roles); - } else { - request.role = new ArrayList<>(user.getProcessRoles()); - } - } - - - /** - * Tasks of case with id "5cb07b6ff05be15f0b972c4d" - * { - * "case": { - * "id": "5cb07b6ff05be15f0b972c4d" - * } - * } - *

- * Tasks of cases with id "5cb07b6ff05be15f0b972c4d" OR "5cb07b6ff05be15f0b972c4e" - * { - * "case": [{ - * "id": "5cb07b6ff05be15f0b972c4d" - * }, - * { - * "id": "5cb07b6ff05be15f0b972c4e" - * }] - * } - *

- * Tasks of case with case title containing "foo" - * { - * "case": { - * "title": "foo" - * } - * } - *

- * Tasks of case with case title containing "foo" OR "bar" - * { - * "case": [{ - * "title": "foo" - * }, - * { - * "title: "bar" - * }] - * } - */ - protected void buildCaseQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { - if (request.useCase == null || request.useCase.isEmpty()) { - return; - } - - BoolQueryBuilder casesQuery = boolQuery(); - request.useCase.stream().map(this::caseRequestQuery).filter(Objects::nonNull).forEach(casesQuery::should); - - query.filter(casesQuery); - } - - /** - * @return query for ID if only ID is present. Query for title if only title is present. - * If both are present an ID query is returned. If neither are present null is returned. - */ - protected QueryBuilder caseRequestQuery(TaskSearchCaseRequest caseRequest) { - if (caseRequest.id != null) { - return termQuery("caseId", caseRequest.id); - } else if (caseRequest.title != null) { - return queryStringQuery("*" + caseRequest.title + "*").fields(this.caseTitledMap); - } - return null; - } - - /** - * Tasks with title (default value) "New task" - * { - * "title": "New task" - * } - *

- * Tasks with title (default value) "New task" OR "Status" - * { - * "title": [ - * "New task", - * "Status" - * ] - * } - */ - protected void buildTitleQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { - if (request.title == null || request.title.isEmpty()) { - return; - } - - BoolQueryBuilder titleQuery = boolQuery(); - for (String title : request.title) { - titleQuery.should(termQuery("title", title)); - } - - query.filter(titleQuery); - } - - /** - * Tasks assigned to user with id 1 - * { - * "user": 1 - * } - *

- * Tasks assigned to user with id 1 OR 2 - */ - protected void buildUserQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { - if (request.user == null || request.user.isEmpty()) { - return; - } - - BoolQueryBuilder userQuery = boolQuery(); - for (String user : request.user) { - userQuery.should(termQuery("userId", user)); - } - - query.filter(userQuery); - } - - /** - * Tasks of process "document" - * { - * "process": "document" - * } - *

- * Tasks of process "document" OR "folder" - * { - * "process": [ - * "document", - * "folder", - * ] - * } - */ - protected void buildProcessQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { - if (request.process == null || request.process.isEmpty()) { - return; - } - - BoolQueryBuilder processQuery = boolQuery(); - for (PetriNet process : request.process) { - if (process.identifier != null) { - processQuery.should(termQuery("processId", process.identifier)); - } - } - - query.filter(processQuery); - } - - /** - * Full text search on fields defined by {@link #fullTextFields()}. - */ - protected void buildFullTextQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { - if (request.fullText == null || request.fullText.isEmpty()) { - return; - } - - QueryBuilder fullTextQuery = queryStringQuery("*" + request.fullText + "*").fields(fullTextFields()); - query.must(fullTextQuery); - } - - /** - * Tasks with transition id "document" - * { - * "transitionId": "document" - * } - *

- * Tasks with transition id "document" OR "folder" - * { - * "transitionId": [ - * "document", - * "folder", - * ] - * } - */ - protected void buildTransitionQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { - if (request.transitionId == null || request.transitionId.isEmpty()) { - return; - } - - BoolQueryBuilder transitionQuery = boolQuery(); - request.transitionId.forEach(transitionId -> transitionQuery.should(termQuery("transitionId", transitionId))); - - query.filter(transitionQuery); - } - - private void buildTagsQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { - if (request.tags == null || request.tags.isEmpty()) { - return; - } - - BoolQueryBuilder tagsQuery = boolQuery(); - for (Map.Entry field : request.tags.entrySet()) { - tagsQuery.must(termQuery("tags." + field.getKey(), field.getValue())); - } - - query.filter(tagsQuery); + public long count(List requests, String actorId, Locale locale, Boolean isIntersection) { + BoolQueryBuilder permissionQuery = permissionQueryBuilder.buildSingleQuery(actorId); + return searchService.count(requests, actorId, locale, isIntersection, permissionQuery); } - /** - * See Query String Query - */ - protected void buildStringQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query, LoggedUser user) { - if (request.query == null || request.query.isEmpty()) { - return; - } - - String populatedQuery = request.query.replaceAll(ElasticQueryConstants.USER_ID_TEMPLATE, user.getId().toString()); - - query.must(queryStringQuery(populatedQuery)); + @Override + public void remove(String taskId) { + ElasticTask task = new ElasticTask(); + task.setTaskId(taskId); + elasticTaskQueueManager.scheduleOperation(new ElasticTaskJob(ElasticJob.REMOVE, task)); } - /** - * Tasks of cases of group with id "5cb07b6ff05be15f0b972c4d" - * { - * "group": "5cb07b6ff05be15f0b972c4d" - * } - *

- * Tasks of cases of group with id "5cb07b6ff05be15f0b972c4d" OR "5cb07b6ff05be15f0b972c4e" - * { - * "transitionId": [ - * "5cb07b6ff05be15f0b972c4d", - * "5cb07b6ff05be15f0b972c4e", - * ] - * } - */ - public boolean buildGroupQuery(TaskSearchRequest request, LoggedUser user, Locale locale, BoolQueryBuilder query) { - if (request.group == null || request.group.isEmpty()) - return false; - - PetriNetSearch processQuery = new PetriNetSearch(); - processQuery.setGroup(request.group); - List groupProcesses = this.petriNetService.search(processQuery, user, new FullPageRequest(), locale).getContent(); - if (groupProcesses.size() == 0) - return true; - - BoolQueryBuilder groupProcessQuery = boolQuery(); - for (PetriNetReference process : groupProcesses) { - groupProcessQuery.should(termQuery("processId", process.getStringId())); - } - - query.filter(groupProcessQuery); - return false; + @Override + public void removeByPetriNetId(String petriNetId) { + elasticTaskQueueManager.removeTasksByProcess(petriNetId); } -} \ No newline at end of file +} diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticViewPermissionService.java b/src/main/java/com/netgrif/application/engine/elastic/service/ElasticViewPermissionService.java deleted file mode 100644 index b3c707b6403..00000000000 --- a/src/main/java/com/netgrif/application/engine/elastic/service/ElasticViewPermissionService.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.netgrif.application.engine.elastic.service; - -import com.netgrif.application.engine.auth.domain.LoggedUser; -import org.elasticsearch.index.query.BoolQueryBuilder; - -import static org.elasticsearch.index.query.QueryBuilders.*; - -public abstract class ElasticViewPermissionService { - - protected void buildViewPermissionQuery(BoolQueryBuilder query, LoggedUser user) { - BoolQueryBuilder viewPermsExists = boolQuery(); - BoolQueryBuilder viewPermNotExists = boolQuery(); - viewPermsExists.should(existsQuery("viewRoles")); - viewPermsExists.should(existsQuery("viewUserRefs")); - viewPermNotExists.mustNot(viewPermsExists); - - /* Build positive view role query */ - BoolQueryBuilder positiveViewRole = buildPositiveViewRoleQuery(viewPermNotExists, user); - - /* Build negative view role query */ - BoolQueryBuilder negativeViewRole = buildNegativeViewRoleQuery(user); - - /* Positive view role set-minus negative view role */ - BoolQueryBuilder positiveRoleSetMinusNegativeRole = setMinus(positiveViewRole, negativeViewRole); - - /* Build positive view userList query */ - BoolQueryBuilder positiveViewUser = buildPositiveViewUser(viewPermNotExists, user); - - /* Role query union positive view userList */ - BoolQueryBuilder roleSetMinusPositiveUserList = union(positiveRoleSetMinusNegativeRole, positiveViewUser); - - /* Build negative view userList query */ - BoolQueryBuilder negativeViewUser = buildNegativeViewUser(user); - - /* Role-UserListPositive set-minus negative view userList */ - BoolQueryBuilder permissionQuery = setMinus(roleSetMinusPositiveUserList, negativeViewUser); - - query.filter(permissionQuery); - } - - private BoolQueryBuilder buildPositiveViewRoleQuery(BoolQueryBuilder viewPermNotExists, LoggedUser user) { - BoolQueryBuilder positiveViewRole = boolQuery(); - BoolQueryBuilder positiveViewRoleQuery = boolQuery(); - for (String roleId : user.getProcessRoles()) { - positiveViewRoleQuery.should(termQuery("viewRoles", roleId)); - } - positiveViewRole.should(viewPermNotExists); - positiveViewRole.should(positiveViewRoleQuery); - return positiveViewRole; - } - - private BoolQueryBuilder buildNegativeViewRoleQuery(LoggedUser user) { - BoolQueryBuilder negativeViewRole = boolQuery(); - BoolQueryBuilder negativeViewRoleQuery = boolQuery(); - for (String roleId : user.getProcessRoles()) { - negativeViewRoleQuery.should(termQuery("negativeViewRoles", roleId)); - } - negativeViewRole.mustNot(negativeViewRoleQuery); - return negativeViewRole; - } - - private BoolQueryBuilder buildPositiveViewUser(BoolQueryBuilder viewPermNotExists, LoggedUser user) { - BoolQueryBuilder positiveViewUser = boolQuery(); - BoolQueryBuilder positiveViewUserQuery = boolQuery(); - positiveViewUserQuery.must(termQuery("viewUsers", user.getId())); - positiveViewUser.should(viewPermNotExists); - positiveViewUser.should(positiveViewUserQuery); - return positiveViewUser; - } - - private BoolQueryBuilder buildNegativeViewUser(LoggedUser user) { - BoolQueryBuilder negativeViewUser = boolQuery(); - BoolQueryBuilder negativeViewUserQuery = boolQuery(); - negativeViewUserQuery.should(termQuery("negativeViewUsers", user.getId())); - negativeViewUser.mustNot(negativeViewUserQuery); - return negativeViewUser; - } - - private BoolQueryBuilder setMinus(BoolQueryBuilder positiveSet, BoolQueryBuilder negativeSet) { - BoolQueryBuilder positiveSetMinusNegativeSet = boolQuery(); - positiveSetMinusNegativeSet.must(positiveSet); - positiveSetMinusNegativeSet.must(negativeSet); - return positiveSetMinusNegativeSet; - } - - private BoolQueryBuilder union(BoolQueryBuilder setA, BoolQueryBuilder setB) { - BoolQueryBuilder unionSet = boolQuery(); - unionSet.should(setA); - unionSet.should(setB); - return unionSet; - } -} diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/ReindexingTask.java b/src/main/java/com/netgrif/application/engine/elastic/service/ReindexingTask.java index 28444c07cff..caad55f767b 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/ReindexingTask.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/ReindexingTask.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.elastic.service; -import com.netgrif.application.engine.elastic.domain.ElasticCaseRepository; +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticCaseRepository; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseMappingService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskMappingService; @@ -39,7 +39,6 @@ public class ReindexingTask { private ElasticCaseRepository elasticCaseRepository; private IElasticCaseService elasticCaseService; private IElasticTaskService elasticTaskService; - private IElasticCaseMappingService caseMappingService; private IElasticTaskMappingService taskMappingService; private IWorkflowService workflowService; @@ -64,7 +63,6 @@ public ReindexingTask( this.elasticCaseRepository = elasticCaseRepository; this.elasticCaseService = elasticCaseService; this.elasticTaskService = elasticTaskService; - this.caseMappingService = caseMappingService; this.taskMappingService = taskMappingService; this.workflowService = workflowService; this.pageSize = pageSize; @@ -77,7 +75,7 @@ public ReindexingTask( @Scheduled(cron = "#{springElasticsearchReindex}") public void reindex() { - log.info("Reindexing stale cases: started reindexing after " + lastRun); + log.info("Reindexing stale cases: started reindexing after {}", lastRun); BooleanExpression predicate = QCase.case$.lastModified.before(LocalDateTime.now()).and(QCase.case$.lastModified.after(lastRun.minusMinutes(2))); @@ -92,7 +90,7 @@ public void reindex() { private void reindexAllPages(BooleanExpression predicate, long count) { long numOfPages = ((count / pageSize) + 1); - log.info("Reindexing " + numOfPages + " pages"); + log.info("Reindexing {} pages", numOfPages); for (int page = 0; page < numOfPages; page++) { reindexPage(predicate, page, numOfPages, false); @@ -104,12 +102,12 @@ public void forceReindexPage(Predicate predicate, int page, long numOfPages) { } private void reindexPage(Predicate predicate, int page, long numOfPages, boolean forced) { - log.info("Reindexing " + (page + 1) + " / " + numOfPages); + log.info("Reindexing {} / {}", page + 1, numOfPages); Page cases = this.workflowService.search(predicate, PageRequest.of(page, pageSize)); for (Case aCase : cases) { if (forced || elasticCaseRepository.countByStringIdAndLastModified(aCase.getStringId(), Timestamp.valueOf(aCase.getLastModified()).getTime()) == 0) { - elasticCaseService.indexNow(this.caseMappingService.transform(aCase)); + elasticCaseService.indexNow(aCase); List tasks = taskRepository.findAllByCaseId(aCase.getStringId()); for (Task task : tasks) { elasticTaskService.indexNow(this.taskMappingService.transform(task)); diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticCaseSearchService.java b/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticCaseSearchService.java new file mode 100644 index 00000000000..a09458e2697 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticCaseSearchService.java @@ -0,0 +1,20 @@ +package com.netgrif.application.engine.elastic.service.interfaces; + +import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; +import com.netgrif.application.engine.workflow.domain.Case; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Locale; + +public interface IElasticCaseSearchService { + + Page search(List requests, @Nullable String actorId, Pageable pageable, Locale locale, + Boolean isIntersection, @Nullable BoolQueryBuilder permissionQuery); + + long count(List requests, @Nullable String actorId, Locale locale, Boolean isIntersection, + @Nullable BoolQueryBuilder permissionQuery); +} diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticCaseService.java b/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticCaseService.java index 024f945aec1..59f428ea133 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticCaseService.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticCaseService.java @@ -1,7 +1,5 @@ package com.netgrif.application.engine.elastic.service.interfaces; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.elastic.domain.ElasticCase; import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; import com.netgrif.application.engine.workflow.domain.Case; import org.springframework.data.domain.Page; @@ -14,17 +12,16 @@ public interface IElasticCaseService { @Async - void index(ElasticCase useCase); + void index(Case useCase); - void indexNow(ElasticCase useCase); - - Page search(List requests, LoggedUser user, Pageable pageable, Locale locale, Boolean isIntersection); - - long count(List requests, LoggedUser user, Locale locale, Boolean isIntersection); + void indexNow(Case useCase); void remove(String caseId); void removeByPetriNetId(String processId); - String findUriNodeId(Case aCase); + Page search(List requests, String actorId, Pageable pageable, Locale locale, + Boolean isIntersection); + + long count(List requests, String actorId, Locale locale, Boolean isIntersection); } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetMappingService.java b/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetMappingService.java index 4106a18ecaa..72015bad33c 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetMappingService.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetMappingService.java @@ -1,8 +1,8 @@ package com.netgrif.application.engine.elastic.service.interfaces; import com.netgrif.application.engine.elastic.domain.ElasticPetriNet; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; public interface IElasticPetriNetMappingService { - ElasticPetriNet transform(PetriNet net); + ElasticPetriNet transform(Process net); } diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetService.java b/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetService.java index 6be7daaf0a3..7f336fe44e1 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetService.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetService.java @@ -1,7 +1,7 @@ package com.netgrif.application.engine.elastic.service.interfaces; import com.netgrif.application.engine.elastic.domain.ElasticPetriNet; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import org.springframework.scheduling.annotation.Async; import java.util.List; @@ -15,8 +15,10 @@ public interface IElasticPetriNetService { void remove(String id); - String findUriNodeId(PetriNet net); + String findUriNodeId(Process net); - List findAllByUriNodeId(String uriNodeId); + List findAllByUriNodeId(String uriNodeId); + + List findAllByIdentifier(String identifier); } diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticTaskSearchService.java b/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticTaskSearchService.java new file mode 100644 index 00000000000..b9bb7fa60d4 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticTaskSearchService.java @@ -0,0 +1,21 @@ +package com.netgrif.application.engine.elastic.service.interfaces; + +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.elastic.web.requestbodies.ElasticTaskSearchRequest; +import com.netgrif.application.engine.workflow.domain.Task; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Locale; + +public interface IElasticTaskSearchService { + + Page search(List requests, String actorId, Pageable pageable, Locale locale, + Boolean isIntersection, @Nullable BoolQueryBuilder permissionQuery); + + long count(List requests, String actorId, Locale locale, Boolean isIntersection, + @Nullable BoolQueryBuilder permissionQuery); +} diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticTaskService.java b/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticTaskService.java index 918ad481962..1355dc540d6 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticTaskService.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticTaskService.java @@ -1,6 +1,5 @@ package com.netgrif.application.engine.elastic.service.interfaces; -import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.elastic.domain.ElasticTask; import com.netgrif.application.engine.elastic.web.requestbodies.ElasticTaskSearchRequest; import com.netgrif.application.engine.workflow.domain.Task; @@ -19,16 +18,18 @@ public interface IElasticTaskService { Future scheduleTaskIndexing(ElasticTask task); + // todo: release/8.0.0 inconsistency with IElasticCaseService (type of input) @Async void index(ElasticTask task); void indexNow(ElasticTask task); - Page search(List requests, LoggedUser user, Pageable pageable, Locale locale, Boolean isIntersection); - - long count(List requests, LoggedUser user, Locale locale, Boolean isIntersection); - void remove(String taskId); void removeByPetriNetId(String petriNetId); + + Page search(List requests, String actorId, Pageable pageable, Locale locale, + Boolean isIntersection); + + long count(List requests, String actorId, Locale locale, Boolean isIntersection); } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/query/ElasticCaseQueryBuilder.java b/src/main/java/com/netgrif/application/engine/elastic/service/query/ElasticCaseQueryBuilder.java new file mode 100644 index 00000000000..aff6c606432 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/elastic/service/query/ElasticCaseQueryBuilder.java @@ -0,0 +1,303 @@ +package com.netgrif.application.engine.elastic.service.query; + +import com.netgrif.application.engine.elastic.domain.ElasticQueryConstants; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCasePrioritySearch; +import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.elasticsearch.core.query.Order; +import org.springframework.stereotype.Service; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import static org.elasticsearch.index.query.QueryBuilders.*; +import static org.elasticsearch.index.query.QueryBuilders.termQuery; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ElasticCaseQueryBuilder implements ElasticQueryBuilder { + + private final IElasticCasePrioritySearch elasticCasePrioritySearch; + + /** + * todo javadoc + * */ + @Override + public BoolQueryBuilder buildSingleQuery(T request, Locale locale, @Nullable String actorId, + @Nullable BoolQueryBuilder permissionQuery) { + CaseSearchRequest typedRequest = (CaseSearchRequest) request; + BoolQueryBuilder query = boolQuery(); + + buildPetriNetQuery(typedRequest, query); + buildAuthorQuery(typedRequest, query); + buildTaskQuery(typedRequest, query); + buildRoleQuery(typedRequest, query); + buildDataQuery(typedRequest, query); + buildFullTextQuery(typedRequest, query); + buildStringQuery(typedRequest, query, actorId); + buildCaseIdQuery(typedRequest, query); + buildUriNodeIdQuery(typedRequest, query); + buildTagsQuery(typedRequest, query); + + if (permissionQuery != null) { + query.filter(permissionQuery); + } + + return query; + } + + public Pageable resolveUnmappedSortAttributes(Pageable pageable) { + if (pageable.isUnpaged()) { + log.warn("Provided pageable is unpaged. Skipping sorting..."); + return pageable; + } + + List modifiedOrders = new ArrayList<>(); + pageable.getSort().iterator().forEachRemaining(order -> modifiedOrders.add(new Order(order.getDirection(), + order.getProperty()).withUnmappedType("keyword"))); + + return PageRequest.of(pageable.getPageNumber(), pageable.getPageSize()).withSort(Sort.by(modifiedOrders)); + } + + private void buildPetriNetQuery(CaseSearchRequest request, BoolQueryBuilder query) { + if (request.process == null || request.process.isEmpty()) { + return; + } + + BoolQueryBuilder petriNetQuery = boolQuery(); + + for (CaseSearchRequest.PetriNet process : request.process) { + if (process.identifier != null) { + petriNetQuery.should(termQuery("processIdentifier", process.identifier)); + } + if (process.processId != null) { + petriNetQuery.should(termQuery("processId", process.processId)); + } + } + + query.filter(petriNetQuery); + } + + /** + *

+     * {
+     *     "author": {
+     *         "email": "user@customer.com"
+     *     }
+     * }
+     * 

+ *

+ * Cases with author with (id 1 AND email "user@customer.com") OR (id 2) + *

+     * {
+     *     "author": [{
+     *         "id": 1
+     *         "email": "user@customer.com"
+     *     }, {
+     *         "id": 2
+     *     }
+     *     ]
+     * }
+     * 

+ */ + private void buildAuthorQuery(CaseSearchRequest request, BoolQueryBuilder query) { + if (request.author == null || request.author.isEmpty()) { + return; + } + + BoolQueryBuilder authorsQuery = boolQuery(); + for (CaseSearchRequest.Author author : request.author) { + BoolQueryBuilder authorQuery = boolQuery(); + if (author.email != null) { + authorQuery.must(termQuery("authorEmail", author.email)); + } + if (author.id != null) { + authorQuery.must(matchQuery("authorId", author.id)); + } + if (author.name != null) { + authorQuery.must(termQuery("authorName", author.name)); + } + authorsQuery.should(authorQuery); + } + + query.filter(authorsQuery); + } + + /** + * Cases with tasks with import Id "nova_uloha" + *
+     * {
+     *     "transition": "nova_uloha"
+     * }
+     * 
+ *

+ * Cases with tasks with import Id "nova_uloha" OR "kontrola" + *

+     * {
+     *     "transition": [
+     *         "nova_uloha",
+     *         "kontrola"
+     *     ]
+     * }
+     * 
+ */ + private void buildTaskQuery(CaseSearchRequest request, BoolQueryBuilder query) { + if (request.transition == null || request.transition.isEmpty()) { + return; + } + + BoolQueryBuilder taskQuery = boolQuery(); + for (String taskImportId : request.transition) { + taskQuery.should(termQuery("taskIds", taskImportId)); + } + + query.filter(taskQuery); + } + + /** + * Cases with active role "5cb07b6ff05be15f0b972c36" + *
+     * {
+     *     "role": "5cb07b6ff05be15f0b972c36"
+     * }
+     * 
+ *

+ * Cases with active role "5cb07b6ff05be15f0b972c36" OR "5cb07b6ff05be15f0b972c31" + *

+     * {
+     *     "role" [
+     *         "5cb07b6ff05be15f0b972c36",
+     *         "5cb07b6ff05be15f0b972c31"
+     *     ]
+     * }
+     * 
+ */ + private void buildRoleQuery(CaseSearchRequest request, BoolQueryBuilder query) { + if (request.role == null || request.role.isEmpty()) { + return; + } + + BoolQueryBuilder roleQuery = boolQuery(); + for (String roleId : request.role) { + roleQuery.should(termQuery("enabledRoles", roleId)); + } + + query.filter(roleQuery); + } + + /** + * Cases where "text_field" has value EXACTLY "text" AND "number_field" has value EXACTLY "125".
+ *
+     * {
+     *     "data": {
+     *         "text_field": "text",
+     *         "number_field": "125"
+     *     }
+     * }
+     * 
+ */ + private void buildDataQuery(CaseSearchRequest request, BoolQueryBuilder query) { + if (request.data == null || request.data.isEmpty()) { + return; + } + + BoolQueryBuilder dataQuery = boolQuery(); + for (Map.Entry field : request.data.entrySet()) { + if (field.getKey().contains(".")) + dataQuery.must(termQuery("dataSet." + field.getKey(), field.getValue())); + else + dataQuery.must(termQuery("dataSet." + field.getKey() + ".fulltextValue.keyword", field.getValue())); + } + + query.filter(dataQuery); + } + + private void buildTagsQuery(CaseSearchRequest request, BoolQueryBuilder query) { + if (request.tags == null || request.tags.isEmpty()) { + return; + } + + BoolQueryBuilder tagsQuery = boolQuery(); + for (Map.Entry field : request.tags.entrySet()) { + tagsQuery.must(termQuery("tags." + field.getKey(), field.getValue())); + } + + query.filter(tagsQuery); + } + + private void buildFullTextQuery(CaseSearchRequest request, BoolQueryBuilder query) { + if (request.fullText == null || request.fullText.isEmpty()) { + return; + } + + // TODO: improvement? wildcard does not scale good + //String searchText = elasticsearchProperties.isAnalyzerEnabled() ? request.fullText : "*" + request.fullText + "*"; + String searchText = "*" + request.fullText + "*"; + QueryBuilder fullTextQuery = queryStringQuery(searchText).fields(elasticCasePrioritySearch.fullTextFields()); + query.must(fullTextQuery); + } + + /** + * See Query String Query + */ + private void buildStringQuery(CaseSearchRequest request, BoolQueryBuilder query, @Nullable String actorId) { + if (request.query == null || request.query.isEmpty()) { + return; + } + + String populatedQuery = request.query; + if (actorId != null) { + populatedQuery = populatedQuery.replaceAll(ElasticQueryConstants.ACTOR_ID_TEMPLATE, actorId); + } + + query.must(queryStringQuery(populatedQuery).allowLeadingWildcard(true).analyzeWildcard(true)); + } + + /** + * Case with stringId "5cb07b6ff05be15f0b972c36" + *
+     * {
+     *     "stringId": "5cb07b6ff05be15f0b972c36"
+     * }
+     * 
+ *

+ * Cases with stringId "5cb07b6ff05be15f0b972c36" OR "5cb07b6ff05be15f0b972c31" + *

+     * {
+     *     "stringId" [
+     *         "5cb07b6ff05be15f0b972c36",
+     *         "5cb07b6ff05be15f0b972c31"
+     *     ]
+     * }
+     * 
+ */ + private void buildCaseIdQuery(CaseSearchRequest request, BoolQueryBuilder query) { + if (request.stringId == null || request.stringId.isEmpty()) { + return; + } + + BoolQueryBuilder caseIdQuery = boolQuery(); + request.stringId.forEach(caseId -> caseIdQuery.should(termQuery("stringId", caseId))); + query.filter(caseIdQuery); + } + + private void buildUriNodeIdQuery(CaseSearchRequest request, BoolQueryBuilder query) { + if (request.uriNodeId == null || request.uriNodeId.isEmpty()) { + return; + } + + BoolQueryBuilder caseIdQuery = boolQuery(); + caseIdQuery.should(termQuery("uriNodeId", request.uriNodeId)); + query.filter(caseIdQuery); + } +} diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/query/ElasticPermissionQueryBuilder.java b/src/main/java/com/netgrif/application/engine/elastic/service/query/ElasticPermissionQueryBuilder.java new file mode 100644 index 00000000000..9eed94ee747 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/elastic/service/query/ElasticPermissionQueryBuilder.java @@ -0,0 +1,138 @@ +package com.netgrif.application.engine.elastic.service.query; + +import com.netgrif.application.engine.authorization.service.interfaces.IRoleAssignmentService; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; +import lombok.RequiredArgsConstructor; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.springframework.stereotype.Service; + +import java.util.Set; + +import static org.elasticsearch.index.query.QueryBuilders.*; +import static org.elasticsearch.index.query.QueryBuilders.boolQuery; + +@Service +@RequiredArgsConstructor +public class ElasticPermissionQueryBuilder { + + private final IRoleAssignmentService roleAssignmentService; + private final ApplicationRoleRunner applicationRoleRunner; + + /** + * todo javadoc + * */ + public BoolQueryBuilder buildSingleQuery(String actorId) { + // Collect assigned roles to user + final Set assignedRoleIds = roleAssignmentService.findAllRoleIdsByActorAndGroups(actorId); + + // Is actor admin? + if (assignedRoleIds.contains(applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE).getStringId())) { + return boolQuery(); + } + + // Check if processRoles or caseRoles exist + BoolQueryBuilder viewPermsExists = boolQuery() + .should(existsQuery("viewProcessRoles")) + .should(existsQuery("viewCaseRoles")); + // Condition where these attributes do NOT exist + BoolQueryBuilder viewPermNotExists = boolQuery() + .mustNot(viewPermsExists); + + // Build queries for each role type + BoolQueryBuilder positiveProcessRole = buildPositiveProcessRoleQuery(viewPermNotExists, assignedRoleIds); + BoolQueryBuilder negativeProcessRole = buildNegativeProcessRoleQuery(assignedRoleIds); + BoolQueryBuilder positiveCaseRole = buildPositiveCaseRoleQuery(viewPermNotExists, assignedRoleIds); + BoolQueryBuilder negativeCaseRole = buildNegativeCaseRoleQuery(assignedRoleIds); + // Calculate final query + return collectQueriesByFormula(positiveProcessRole, negativeProcessRole, + positiveCaseRole, negativeCaseRole); + } + + /** + * todo javadoc + * Build a positive view role query using termsQuery for efficiency. + * This reduces the number of clauses by sending all roles at once. + */ + private BoolQueryBuilder buildPositiveProcessRoleQuery(BoolQueryBuilder viewPermNotExists, Set roleIds) { + BoolQueryBuilder positiveProcessRole = boolQuery(); + if (!roleIds.isEmpty()) { + positiveProcessRole.should(termsQuery("positiveViewProcessRoles", roleIds)); + } + positiveProcessRole.should(viewPermNotExists); + return positiveProcessRole; + } + + /** + * todo javadoc + * Build a negative view role query by excluding negative roles. + */ + private BoolQueryBuilder buildNegativeProcessRoleQuery(Set roleIds) { + BoolQueryBuilder negativeProcessRole = boolQuery(); + if (!roleIds.isEmpty()) { + negativeProcessRole.mustNot(termsQuery("negativeViewProcessRoles", roleIds)); + } + return negativeProcessRole; + } + + /** + * todo javadoc + * Build a positive view user query using filter (as score is not needed). + */ + private BoolQueryBuilder buildPositiveCaseRoleQuery(BoolQueryBuilder viewPermNotExists, Set roleIds) { + BoolQueryBuilder positiveCaseRole = boolQuery(); + if (!roleIds.isEmpty()) { + positiveCaseRole.should(termsQuery("positiveViewCaseRoles", roleIds)); + } + positiveCaseRole.should(viewPermNotExists); + return positiveCaseRole; + } + + /** + * todo javadoc + * */ + private BoolQueryBuilder buildNegativeCaseRoleQuery(Set roleIds) { + BoolQueryBuilder negativeCaseRole = boolQuery(); + if (!roleIds.isEmpty()) { + negativeCaseRole.mustNot(termsQuery("negativeViewCaseRoles", roleIds)); + } + return negativeCaseRole; + } + + /** + * todo javadoc + * Calculate resulting condition, which must be matched in order to search document + * $$((R_{p} \setminus R_{n}) \cup U_{p}) \setminus U_{n}$$ + * $\setminus$ - seminus, e.g. $A \setminus B$ = every element from A that is not in B + * $\cup$ - union of sets + * $R_{p}$ - set of roles that are assigned to user and define given permission with true (grant the permission) + * $R_{n}$ - set of roles that are assigned to user and define given permission with false (forbid the permission) + * $U_{p}$ - set of user lists that user is part of and define given permission with true (grant the permission) + * $U_{n}$ - set of user lists that user is part of and define given permission with false (forbid the permission) + * */ + private BoolQueryBuilder collectQueriesByFormula(BoolQueryBuilder positiveProcessRole, BoolQueryBuilder negativeProcessRole, + BoolQueryBuilder positiveCaseRole, BoolQueryBuilder negativeCaseRole) { + BoolQueryBuilder processRoleDiff = setMinus(positiveProcessRole, negativeProcessRole); + BoolQueryBuilder processRoleDiffUnionPositiveCaseRole = union(processRoleDiff, positiveCaseRole); + return setMinus(processRoleDiffUnionPositiveCaseRole, negativeCaseRole); + } + + /** + * todo javadoc + * */ + private BoolQueryBuilder setMinus(BoolQueryBuilder positiveSet, BoolQueryBuilder negativeSet) { + return boolQuery() + .must(positiveSet) + .must(negativeSet); + } + + /** + * todo javadoc + * Unions two queries using OR with a minimum_should_match of 1. + */ + private BoolQueryBuilder union(BoolQueryBuilder setA, BoolQueryBuilder setB) { + return boolQuery() + .should(setA) + .should(setB) + .minimumShouldMatch(1); + } +} diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/query/ElasticQueryBuilder.java b/src/main/java/com/netgrif/application/engine/elastic/service/query/ElasticQueryBuilder.java new file mode 100644 index 00000000000..142d57358b6 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/elastic/service/query/ElasticQueryBuilder.java @@ -0,0 +1,11 @@ +package com.netgrif.application.engine.elastic.service.query; + +import org.elasticsearch.index.query.BoolQueryBuilder; + +import javax.annotation.Nullable; +import java.util.Locale; + +public interface ElasticQueryBuilder { + BoolQueryBuilder buildSingleQuery(T request, Locale locale, @Nullable String actorId, + @Nullable BoolQueryBuilder permissionQuery); +} diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/query/ElasticTaskQueryBuilder.java b/src/main/java/com/netgrif/application/engine/elastic/service/query/ElasticTaskQueryBuilder.java new file mode 100644 index 00000000000..83a31cffa9e --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/elastic/service/query/ElasticTaskQueryBuilder.java @@ -0,0 +1,270 @@ +package com.netgrif.application.engine.elastic.service.query; + +import com.google.common.collect.ImmutableMap; +import com.netgrif.application.engine.elastic.domain.ElasticQueryConstants; +import com.netgrif.application.engine.elastic.web.requestbodies.ElasticTaskSearchRequest; +import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.PetriNet; +import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.TaskSearchCaseRequest; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.index.query.QueryStringQueryBuilder; +import org.springframework.stereotype.Service; + +import javax.annotation.Nullable; +import java.util.*; + +import static org.elasticsearch.index.query.QueryBuilders.*; + +@Service +public class ElasticTaskQueryBuilder implements ElasticQueryBuilder { + + private final Map fullTextFieldMap = ImmutableMap.of( + "title", 1f, + "caseTitle", 1f + ); + + private final Map caseTitledMap = ImmutableMap.of( + "caseTitle", 1f + ); + + /** + * todo javadoc + * */ + @Override + public BoolQueryBuilder buildSingleQuery(T request, Locale locale, @Nullable String actorId, + @Nullable BoolQueryBuilder permissionQuery) { + if (request == null) { + throw new IllegalArgumentException("Request can not be null!"); + } + + ElasticTaskSearchRequest typedRequest = (ElasticTaskSearchRequest) request; + + BoolQueryBuilder query = boolQuery(); + buildCaseQuery(typedRequest, query); + buildTitleQuery(typedRequest, query); + buildAssigneeQuery(typedRequest, query); + buildProcessQuery(typedRequest, query); + buildFullTextQuery(typedRequest, query); + buildTransitionQuery(typedRequest, query); + buildTagsQuery(typedRequest, query); + buildStringQuery(typedRequest, query, actorId); + + if (permissionQuery != null) { + query.filter(permissionQuery); + } + + return query; + } + + /** + * See {@link QueryStringQueryBuilder#fields(Map)} + * + * @return map where keys are ElasticCase field names and values are boosts of these fields + */ + public Map fullTextFields() { + return fullTextFieldMap; + } + + /** + * Tasks of case with id "5cb07b6ff05be15f0b972c4d" + * { + * "case": { + * "id": "5cb07b6ff05be15f0b972c4d" + * } + * } + *

+ * Tasks of cases with id "5cb07b6ff05be15f0b972c4d" OR "5cb07b6ff05be15f0b972c4e" + * { + * "case": [{ + * "id": "5cb07b6ff05be15f0b972c4d" + * }, + * { + * "id": "5cb07b6ff05be15f0b972c4e" + * }] + * } + *

+ * Tasks of case with case title containing "foo" + * { + * "case": { + * "title": "foo" + * } + * } + *

+ * Tasks of case with case title containing "foo" OR "bar" + * { + * "case": [{ + * "title": "foo" + * }, + * { + * "title: "bar" + * }] + * } + */ + private void buildCaseQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { + if (request.useCase == null || request.useCase.isEmpty()) { + return; + } + + BoolQueryBuilder casesQuery = boolQuery(); + request.useCase.stream().map(this::caseRequestQuery).filter(Objects::nonNull).forEach(casesQuery::should); + + query.filter(casesQuery); + } + + /** + * @return query for ID if only ID is present. Query for title if only title is present. + * If both are present an ID query is returned. If neither are present null is returned. + */ + private QueryBuilder caseRequestQuery(TaskSearchCaseRequest caseRequest) { + if (caseRequest.id != null) { + return termQuery("caseId", caseRequest.id); + } else if (caseRequest.title != null) { + return queryStringQuery("*" + caseRequest.title + "*").fields(this.caseTitledMap); + } + return null; + } + + /** + * Tasks with title (default value) "New task" + * { + * "title": "New task" + * } + *

+ * Tasks with title (default value) "New task" OR "Status" + * { + * "title": [ + * "New task", + * "Status" + * ] + * } + */ + private void buildTitleQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { + if (request.title == null || request.title.isEmpty()) { + return; + } + + BoolQueryBuilder titleQuery = boolQuery(); + for (String title : request.title) { + titleQuery.should(termQuery("title", title)); + } + + query.filter(titleQuery); + } + + /** + * todo javadoc + * Tasks assigned to user with id 1 + * { + * "user": 1 + * } + *

+ * Tasks assigned to user with id 1 OR 2 + */ + private void buildAssigneeQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { + if (request.assigneeId == null || request.assigneeId.isEmpty()) { + return; + } + + BoolQueryBuilder assigneeQuery = boolQuery(); + for (String assigneeId : request.assigneeId) { + assigneeQuery.should(termQuery("assigneeId", assigneeId)); + } + + query.filter(assigneeQuery); + } + + /** + * Tasks of process "document" + * { + * "process": "document" + * } + *

+ * Tasks of process "document" OR "folder" + * { + * "process": [ + * "document", + * "folder", + * ] + * } + */ + private void buildProcessQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { + if (request.process == null || request.process.isEmpty()) { + return; + } + + BoolQueryBuilder processQuery = boolQuery(); + for (PetriNet process : request.process) { + if (process.identifier != null) { + processQuery.should(termQuery("processId", process.identifier)); + } + } + + query.filter(processQuery); + } + + /** + * Full text search on fields defined by {@link #fullTextFields()}. + */ + private void buildFullTextQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { + if (request.fullText == null || request.fullText.isEmpty()) { + return; + } + + QueryBuilder fullTextQuery = queryStringQuery("*" + request.fullText + "*").fields(fullTextFields()); + query.must(fullTextQuery); + } + + /** + * Tasks with transition id "document" + * { + * "transitionId": "document" + * } + *

+ * Tasks with transition id "document" OR "folder" + * { + * "transitionId": [ + * "document", + * "folder", + * ] + * } + */ + private void buildTransitionQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { + if (request.transitionId == null || request.transitionId.isEmpty()) { + return; + } + + BoolQueryBuilder transitionQuery = boolQuery(); + request.transitionId.forEach(transitionId -> transitionQuery.should(termQuery("transitionId", transitionId))); + + query.filter(transitionQuery); + } + + private void buildTagsQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query) { + if (request.properties == null || request.properties.isEmpty()) { + return; + } + + BoolQueryBuilder tagsQuery = boolQuery(); + for (Map.Entry field : request.properties.entrySet()) { + tagsQuery.must(termQuery("tags." + field.getKey(), field.getValue())); + } + + query.filter(tagsQuery); + } + + /** + * See Query String Query + */ + private void buildStringQuery(ElasticTaskSearchRequest request, BoolQueryBuilder query, @Nullable String actorId) { + if (request.query == null || request.query.isEmpty()) { + return; + } + + String populatedQuery = request.query; + if (actorId != null) { + populatedQuery = request.query.replaceAll(ElasticQueryConstants.ACTOR_ID_TEMPLATE, actorId); + } + + query.must(queryStringQuery(populatedQuery)); + } +} diff --git a/src/main/java/com/netgrif/application/engine/elastic/service/transform/UserListFieldTransformer.java b/src/main/java/com/netgrif/application/engine/elastic/service/transform/UserListFieldTransformer.java index 09c66ec84d9..32857ddde3b 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/service/transform/UserListFieldTransformer.java +++ b/src/main/java/com/netgrif/application/engine/elastic/service/transform/UserListFieldTransformer.java @@ -22,10 +22,10 @@ public UserField transform(UserListField caseField, UserListField petriNetField) return null; } List userData = value.getUserValues().stream() - .map(user -> new UserField.UserMappingData( - user.getId(), - user.getEmail(), - user.getFullName() + .map(actor -> new UserField.UserMappingData( + actor.getId(), + actor.getEmail(), + actor.getFullName() )) .collect(Collectors.toList()); return new UserField(userData); diff --git a/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java b/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java index d32dc976069..a971b42d9c9 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java +++ b/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java @@ -15,7 +15,6 @@ import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -42,7 +41,7 @@ public ElasticController(IWorkflowService workflowService, ReindexingTask reinde this.properties = properties; } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") @Operation(summary = "Reindex specified cases", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -61,10 +60,10 @@ public MessageResource reindex(@RequestBody Predicate predicate) { } long numOfPages = (count / properties.getReindexExecutor().getSize()) + 1; - log.info("Reindexing cases: " + numOfPages + " pages"); + log.info("Reindexing cases: {} pages", numOfPages); for (int page = 0; page < numOfPages; page++) { - log.info("Indexing page " + (page + 1)); + log.info("Indexing page {}", (page + 1)); reindexingTask.forceReindexPage(predicate, page, numOfPages); } return MessageResource.successMessage("Success"); diff --git a/src/main/java/com/netgrif/application/engine/elastic/web/requestbodies/CaseSearchRequest.java b/src/main/java/com/netgrif/application/engine/elastic/web/requestbodies/CaseSearchRequest.java index 55cac8a2f50..cd0bbd06880 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/web/requestbodies/CaseSearchRequest.java +++ b/src/main/java/com/netgrif/application/engine/elastic/web/requestbodies/CaseSearchRequest.java @@ -42,9 +42,6 @@ public class CaseSearchRequest { @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public List stringId; - @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) - public List group; - public Map tags; public CaseSearchRequest(Map request) { @@ -86,9 +83,6 @@ public CaseSearchRequest(Map request) { if (request.containsKey("stringId") && request.get("stringId") instanceof List) { this.stringId = (List) request.get("stringId"); } - if (request.containsKey("group") && request.get("group") instanceof List) { - this.group = (List) request.get("group"); - } } @Data diff --git a/src/main/java/com/netgrif/application/engine/elastic/web/requestbodies/ElasticTaskSearchRequest.java b/src/main/java/com/netgrif/application/engine/elastic/web/requestbodies/ElasticTaskSearchRequest.java index a01e639ae7f..635c1da3901 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/web/requestbodies/ElasticTaskSearchRequest.java +++ b/src/main/java/com/netgrif/application/engine/elastic/web/requestbodies/ElasticTaskSearchRequest.java @@ -16,6 +16,7 @@ public class ElasticTaskSearchRequest extends TaskSearchRequest { public String query; public ElasticTaskSearchRequest(Map request) { + // todo: release/8.0.0 if (request.containsKey("role") && request.get("role") instanceof List) { this.role = (List) request.get("role"); } @@ -33,8 +34,8 @@ public ElasticTaskSearchRequest(Map request) { if (request.containsKey("title") && request.get("title") instanceof List) { this.title = (List) request.get("title"); } - if (request.containsKey("user") && request.get("user") instanceof List) { - this.user = (List) request.get("user"); + if (request.containsKey("assigneeId") && request.get("assigneeId") instanceof List) { + this.assigneeId = (List) request.get("assigneeId"); } if (request.containsKey("process") && request.get("process") instanceof List) { List processIdentifiers = (List) request.get("process"); @@ -46,12 +47,6 @@ public ElasticTaskSearchRequest(Map request) { if (request.containsKey("fullText") && request.get("fullText") instanceof String) { this.fullText = (String) request.get("fullText"); } - if (request.containsKey("group") && request.get("group") instanceof List) { - this.group = (List) request.get("group"); - } - if (request.containsKey("users") && request.get("users") instanceof List) { - this.users = (List) request.get("users"); - } if (request.containsKey("query") && request.get("query") instanceof String) { this.query = (String) request.get("query"); } diff --git a/src/main/java/com/netgrif/application/engine/event/events/Event.java b/src/main/java/com/netgrif/application/engine/event/events/Event.java index 82a977bd4b6..f2238595554 100644 --- a/src/main/java/com/netgrif/application/engine/event/events/Event.java +++ b/src/main/java/com/netgrif/application/engine/event/events/Event.java @@ -5,9 +5,9 @@ import java.time.LocalDateTime; +@Getter public abstract class Event extends ApplicationEvent { - @Getter protected LocalDateTime time; public Event(Object source) { diff --git a/src/main/java/com/netgrif/application/engine/event/events/authentication/IdentityEvent.java b/src/main/java/com/netgrif/application/engine/event/events/authentication/IdentityEvent.java new file mode 100644 index 00000000000..6a14023fc80 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/event/events/authentication/IdentityEvent.java @@ -0,0 +1,16 @@ +package com.netgrif.application.engine.event.events.authentication; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.event.events.Event; +import lombok.Getter; + +@Getter +public abstract class IdentityEvent extends Event { + + protected final Identity identity; + + public IdentityEvent(Identity identity) { + super(identity); + this.identity = identity; + } +} diff --git a/src/main/java/com/netgrif/application/engine/event/events/authentication/IdentityLoginEvent.java b/src/main/java/com/netgrif/application/engine/event/events/authentication/IdentityLoginEvent.java new file mode 100644 index 00000000000..ac7b1450c66 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/event/events/authentication/IdentityLoginEvent.java @@ -0,0 +1,17 @@ +package com.netgrif.application.engine.event.events.authentication; + +import com.netgrif.application.engine.authentication.domain.Identity; + +public class IdentityLoginEvent extends IdentityEvent { + + // todo: release/8.0.0 needed? Spring security publishes AuthenticationSuccessEvent + + public IdentityLoginEvent(Identity identity) { + super(identity); + } + + @Override + public String getMessage() { + return ""; + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/event/events/authentication/IdentityLogoutEvent.java b/src/main/java/com/netgrif/application/engine/event/events/authentication/IdentityLogoutEvent.java new file mode 100644 index 00000000000..36201d9289d --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/event/events/authentication/IdentityLogoutEvent.java @@ -0,0 +1,17 @@ +package com.netgrif.application.engine.event.events.authentication; + +import com.netgrif.application.engine.authentication.domain.Identity; + +public class IdentityLogoutEvent extends IdentityEvent { + + // todo: release/8.0.0 remove or keep (call as result of /logout ?) + + public IdentityLogoutEvent(Identity identity) { + super(identity); + } + + @Override + public String getMessage() { + return ""; + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/event/events/authentication/IdentityRegistrationEvent.java b/src/main/java/com/netgrif/application/engine/event/events/authentication/IdentityRegistrationEvent.java new file mode 100644 index 00000000000..6bc999192b0 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/event/events/authentication/IdentityRegistrationEvent.java @@ -0,0 +1,16 @@ +package com.netgrif.application.engine.event.events.authentication; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.utils.DateUtils; + +public class IdentityRegistrationEvent extends IdentityEvent { + + public IdentityRegistrationEvent(Identity identity) { + super(identity); + } + + @Override + public String getMessage() { + return String.format("New identity %s registered on %s", identity.getUsername(), DateUtils.toString(time)); + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/event/events/authorization/ActorAssignRoleEvent.java b/src/main/java/com/netgrif/application/engine/event/events/authorization/ActorAssignRoleEvent.java new file mode 100644 index 00000000000..df40d5aed20 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/event/events/authorization/ActorAssignRoleEvent.java @@ -0,0 +1,30 @@ +package com.netgrif.application.engine.event.events.authorization; + +import com.netgrif.application.engine.authorization.domain.Actor; +import com.netgrif.application.engine.authorization.domain.Role; +import lombok.Getter; + +import java.util.Collection; + +@Getter +public class ActorAssignRoleEvent extends ActorEvent { + + protected final Collection roles; + + public ActorAssignRoleEvent(Actor actor, Collection roles) { + super(actor); + this.roles = roles; + } + + @Override + public String getMessage() { + StringBuilder sb = new StringBuilder("Roles "); + roles.forEach(role -> { + sb.append(role.getTitleAsString()); + sb.append(","); + }); + sb.append(" assigned to actor "); + sb.append(actor.getName()); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/event/events/authorization/ActorEvent.java b/src/main/java/com/netgrif/application/engine/event/events/authorization/ActorEvent.java new file mode 100644 index 00000000000..b48eefdfd51 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/event/events/authorization/ActorEvent.java @@ -0,0 +1,16 @@ +package com.netgrif.application.engine.event.events.authorization; + +import com.netgrif.application.engine.authorization.domain.Actor; +import com.netgrif.application.engine.event.events.Event; +import lombok.Getter; + +@Getter +public abstract class ActorEvent extends Event { + + protected final Actor actor; + + public ActorEvent(Actor actor) { + super(actor); + this.actor = actor; + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/event/events/authorization/ActorRemoveRoleEvent.java b/src/main/java/com/netgrif/application/engine/event/events/authorization/ActorRemoveRoleEvent.java new file mode 100644 index 00000000000..2ce7ff9b9ed --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/event/events/authorization/ActorRemoveRoleEvent.java @@ -0,0 +1,30 @@ +package com.netgrif.application.engine.event.events.authorization; + +import com.netgrif.application.engine.authorization.domain.Actor; +import com.netgrif.application.engine.authorization.domain.Role; +import lombok.Getter; + +import java.util.Collection; + +@Getter +public class ActorRemoveRoleEvent extends ActorEvent { + + protected final Collection roles; + + public ActorRemoveRoleEvent(Actor actor, Collection roles) { + super(actor); + this.roles = roles; + } + + @Override + public String getMessage() { + StringBuilder sb = new StringBuilder("Roles "); + roles.forEach(role -> { + sb.append(role.getTitleAsString()); + sb.append(","); + }); + sb.append(" removed from actor "); + sb.append(actor.getName()); + return sb.toString(); + } +} diff --git a/src/main/java/com/netgrif/application/engine/event/events/user/AdminActionEvent.java b/src/main/java/com/netgrif/application/engine/event/events/user/AdminActionEvent.java deleted file mode 100644 index c80e4cd4620..00000000000 --- a/src/main/java/com/netgrif/application/engine/event/events/user/AdminActionEvent.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.netgrif.application.engine.event.events.user; - -import com.netgrif.application.engine.auth.domain.LoggedUser; -import lombok.Data; - -@Data -public class AdminActionEvent extends UserEvent { - - private String code; - - public AdminActionEvent(LoggedUser user, String code) { - super(user); - this.code = code; - } - - @Override - public String getMessage() { - return "User " + user.getUsername() + " run following script: " + code; - } -} diff --git a/src/main/java/com/netgrif/application/engine/event/events/user/UserEvent.java b/src/main/java/com/netgrif/application/engine/event/events/user/UserEvent.java deleted file mode 100644 index e4403fbf7ff..00000000000 --- a/src/main/java/com/netgrif/application/engine/event/events/user/UserEvent.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.netgrif.application.engine.event.events.user; - -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.event.events.Event; -import lombok.Getter; - -public abstract class UserEvent extends Event { - - @Getter - protected final LoggedUser user; - - public UserEvent(LoggedUser user) { - super(user); - this.user = user; - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/event/events/user/UserLoginEvent.java b/src/main/java/com/netgrif/application/engine/event/events/user/UserLoginEvent.java deleted file mode 100644 index 26ec0d3c93d..00000000000 --- a/src/main/java/com/netgrif/application/engine/event/events/user/UserLoginEvent.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.netgrif.application.engine.event.events.user; - -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.utils.DateUtils; - -public class UserLoginEvent extends UserEvent { - - public UserLoginEvent(LoggedUser user) { - super(user); - } - - @Override - public String getMessage() { - return "User " + user.getUsername() + " logged in on " + DateUtils.toString(time); - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/event/events/user/UserLogoutEvent.java b/src/main/java/com/netgrif/application/engine/event/events/user/UserLogoutEvent.java deleted file mode 100644 index 8047b79de0b..00000000000 --- a/src/main/java/com/netgrif/application/engine/event/events/user/UserLogoutEvent.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.netgrif.application.engine.event.events.user; - -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.utils.DateUtils; - -public class UserLogoutEvent extends UserEvent { - - public UserLogoutEvent(LoggedUser user) { - super(user); - } - - @Override - public String getMessage() { - return "User " + user.getUsername() + " logged out on " + DateUtils.toString(time); - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/event/events/user/UserRegistrationEvent.java b/src/main/java/com/netgrif/application/engine/event/events/user/UserRegistrationEvent.java deleted file mode 100644 index a745ecfd412..00000000000 --- a/src/main/java/com/netgrif/application/engine/event/events/user/UserRegistrationEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.netgrif.application.engine.event.events.user; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.domain.RegisteredUser; -import com.netgrif.application.engine.utils.DateUtils; - -public class UserRegistrationEvent extends UserEvent { - - public UserRegistrationEvent(RegisteredUser user) { - super(new LoggedUser( - user.getStringId(), - user.getEmail(), - user.getPassword(), - user.getAuthorities() - )); - } - - public UserRegistrationEvent(LoggedUser user) { - super(user); - } - - public UserRegistrationEvent(IUser user) { - super(new LoggedUser( - user.getStringId(), - user.getEmail(), - "", - user.getAuthorities() - )); - } - - @Override - public String getMessage() { - return "New user " + user.getUsername() + " registered on " + DateUtils.toString(time); - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/event/events/user/UserRoleChangeEvent.java b/src/main/java/com/netgrif/application/engine/event/events/user/UserRoleChangeEvent.java deleted file mode 100644 index fecb89598ec..00000000000 --- a/src/main/java/com/netgrif/application/engine/event/events/user/UserRoleChangeEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.netgrif.application.engine.event.events.user; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import lombok.Getter; - -import java.util.Collection; - -public class UserRoleChangeEvent extends UserEvent { - - @Getter - protected final Collection roles; - - public UserRoleChangeEvent(LoggedUser user, Collection roles) { - super(user); - this.roles = roles; - } - - public UserRoleChangeEvent(IUser user, Collection roles) { - super(user.transformToLoggedUser()); - this.roles = roles; - } - - @Override - public String getMessage() { - StringBuilder sb = new StringBuilder("Roles "); - roles.forEach(role -> { - sb.append(role.getName()); - sb.append(","); - }); - sb.append(" assigned to user "); - sb.append(user.getUsername()); - return sb.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/event/listeners/AuthEventListener.java b/src/main/java/com/netgrif/application/engine/event/listeners/AuthEventListener.java index 7d5111ba76c..96e2aee4d3f 100644 --- a/src/main/java/com/netgrif/application/engine/event/listeners/AuthEventListener.java +++ b/src/main/java/com/netgrif/application/engine/event/listeners/AuthEventListener.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.event.listeners; -import com.netgrif.application.engine.auth.service.interfaces.ILoginAttemptService; +import com.netgrif.application.engine.authentication.service.interfaces.ILoginAttemptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.context.event.EventListener; diff --git a/src/main/java/com/netgrif/application/engine/export/service/ExportService.java b/src/main/java/com/netgrif/application/engine/export/service/ExportService.java index 5cb141defb3..74a7b68757c 100644 --- a/src/main/java/com/netgrif/application/engine/export/service/ExportService.java +++ b/src/main/java/com/netgrif/application/engine/export/service/ExportService.java @@ -1,7 +1,6 @@ package com.netgrif.application.engine.export.service; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; @@ -9,7 +8,6 @@ import com.netgrif.application.engine.export.configuration.ExportConfiguration; import com.netgrif.application.engine.export.domain.ExportDataConfig; import com.netgrif.application.engine.export.service.interfaces.IExportService; -import com.netgrif.application.engine.petrinet.domain.I18nString; import com.netgrif.application.engine.petrinet.domain.dataset.*; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; @@ -27,9 +25,7 @@ import java.io.*; import java.nio.charset.StandardCharsets; -import java.time.LocalDate; import java.util.*; -import java.util.stream.Collectors; @Slf4j @Service @@ -51,13 +47,13 @@ public class ExportService implements IExportService { private ITaskService taskService; @Autowired - private TaskRepository taskRepository; + private IUserService userService; @Autowired - private ExportConfiguration exportConfiguration; + private TaskRepository taskRepository; @Autowired - private IUserService userService; + private ExportConfiguration exportConfiguration; @Override @@ -101,39 +97,39 @@ public OutputStream fillCsvCaseData(Predicate predicate, File outFile, ExportDat @Override public OutputStream fillCsvCaseData(List requests, File outFile) throws FileNotFoundException { - return fillCsvCaseData(requests, outFile, null, userService.getLoggedOrSystem().transformToLoggedUser(), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); + return fillCsvCaseData(requests, outFile, null, userService.getSystemUser().getStringId(), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); } @Override public OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config) throws FileNotFoundException { - return fillCsvCaseData(requests, outFile, config, userService.getLoggedOrSystem().transformToLoggedUser(), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); + return fillCsvCaseData(requests, outFile, config, userService.getSystemUser().getStringId(), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); } @Override public OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config, - LoggedUser user) throws FileNotFoundException { - return fillCsvCaseData(requests, outFile, config, user, exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); + String actorId) throws FileNotFoundException { + return fillCsvCaseData(requests, outFile, config, actorId, exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); } @Override public OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config, - LoggedUser user, int pageSize) throws FileNotFoundException { - return fillCsvCaseData(requests, outFile, config, user, pageSize, LocaleContextHolder.getLocale(), false); + String actorId, int pageSize) throws FileNotFoundException { + return fillCsvCaseData(requests, outFile, config, actorId, pageSize, LocaleContextHolder.getLocale(), false); } @Override public OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config, - LoggedUser user, int pageSize, Locale locale) throws FileNotFoundException { - return fillCsvCaseData(requests, outFile, config, user, pageSize, locale, false); + String actorId, int pageSize, Locale locale) throws FileNotFoundException { + return fillCsvCaseData(requests, outFile, config, actorId, pageSize, locale, false); } @Override public OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config, - LoggedUser user, int pageSize, Locale locale, Boolean isIntersection) throws FileNotFoundException { - int numOfPages = (int) ((elasticCaseService.count(requests, user, locale, isIntersection) / pageSize) + 1); + String actorId, int pageSize, Locale locale, Boolean isIntersection) throws FileNotFoundException { + int numOfPages = (int) ((elasticCaseService.count(requests, actorId, locale, isIntersection) / pageSize) + 1); List exportCases = new ArrayList<>(); for (int i = 0; i < numOfPages; i++) { - exportCases.addAll(elasticCaseService.search(requests, user, PageRequest.of(i, pageSize), locale, isIntersection).toList()); + exportCases.addAll(elasticCaseService.search(requests, actorId, PageRequest.of(i, pageSize), locale, isIntersection).toList()); } return buildCaseCsv(exportCases, config, outFile); } @@ -159,40 +155,40 @@ public OutputStream buildCaseCsv(List exportCases, ExportDataConfig config @Override public OutputStream fillCsvTaskData(List requests, File outFile) throws FileNotFoundException { - return fillCsvTaskData(requests, outFile, null, userService.getLoggedOrSystem().transformToLoggedUser(), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); + return fillCsvTaskData(requests, outFile, null, userService.getSystemUser().getStringId(), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); } @Override public OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config) throws FileNotFoundException { - return fillCsvTaskData(requests, outFile, config, userService.getLoggedOrSystem().transformToLoggedUser(), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); + return fillCsvTaskData(requests, outFile, config, userService.getSystemUser().getStringId(), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); } @Override public OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config, - LoggedUser user) throws FileNotFoundException { - return fillCsvTaskData(requests, outFile, config, user, exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); + String actorId) throws FileNotFoundException { + return fillCsvTaskData(requests, outFile, config, actorId, exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); } @Override public OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config, - LoggedUser user, int pageSize) throws FileNotFoundException { - return fillCsvTaskData(requests, outFile, config, user, pageSize, LocaleContextHolder.getLocale(), false); + String actorId, int pageSize) throws FileNotFoundException { + return fillCsvTaskData(requests, outFile, config, actorId, pageSize, LocaleContextHolder.getLocale(), false); } @Override public OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config, - LoggedUser user, int pageSize, Locale locale) throws FileNotFoundException { - return fillCsvTaskData(requests, outFile, config, user, pageSize, locale, false); + String actorId, int pageSize, Locale locale) throws FileNotFoundException { + return fillCsvTaskData(requests, outFile, config, actorId, pageSize, locale, false); } @Override public OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config, - LoggedUser user, int pageSize, Locale locale, Boolean isIntersection) throws FileNotFoundException { - int numberOfTasks = (int) ((elasticTaskService.count(requests, user, locale, isIntersection) / pageSize) + 1); + String actorId, int pageSize, Locale locale, Boolean isIntersection) throws FileNotFoundException { + int numberOfTasks = (int) ((elasticTaskService.count(requests, actorId, locale, isIntersection) / pageSize) + 1); List exportTasks = new ArrayList<>(); for (int i = 0; i < numberOfTasks; i++) { - exportTasks.addAll(elasticTaskService.search(requests, user, PageRequest.of(0, pageSize), locale, isIntersection).toList()); + exportTasks.addAll(elasticTaskService.search(requests, actorId, PageRequest.of(0, pageSize), locale, isIntersection).toList()); } return buildTaskCsv(exportTasks, config, outFile); } diff --git a/src/main/java/com/netgrif/application/engine/export/service/interfaces/IExportService.java b/src/main/java/com/netgrif/application/engine/export/service/interfaces/IExportService.java index 0bd17beca34..2c6bd5a6e96 100644 --- a/src/main/java/com/netgrif/application/engine/export/service/interfaces/IExportService.java +++ b/src/main/java/com/netgrif/application/engine/export/service/interfaces/IExportService.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.export.service.interfaces; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; import com.netgrif.application.engine.elastic.web.requestbodies.ElasticTaskSearchRequest; import com.netgrif.application.engine.export.domain.ExportDataConfig; @@ -31,13 +32,13 @@ public interface IExportService { OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config) throws FileNotFoundException; - OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config, LoggedUser user) throws FileNotFoundException; + OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config, String actorId) throws FileNotFoundException; - OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config, LoggedUser user, int pageSize) throws FileNotFoundException; + OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config, String actorId, int pageSize) throws FileNotFoundException; - OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config, LoggedUser user, int pageSize, Locale locale) throws FileNotFoundException; + OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config, String actorId, int pageSize, Locale locale) throws FileNotFoundException; - OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config, LoggedUser user, int pageSize, Locale locale, Boolean isIntersection) throws FileNotFoundException; + OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config, String actorId, int pageSize, Locale locale, Boolean isIntersection) throws FileNotFoundException; OutputStream fillCsvTaskData(Predicate predicate, File outFile) throws FileNotFoundException; @@ -51,13 +52,13 @@ public interface IExportService { OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config) throws FileNotFoundException; - OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config, LoggedUser user) throws FileNotFoundException; + OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config, String actorId) throws FileNotFoundException; - OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config, LoggedUser user, int pageSize) throws FileNotFoundException; + OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config, String actorId, int pageSize) throws FileNotFoundException; - OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config, LoggedUser user, int pageSize, Locale locale) throws FileNotFoundException; + OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config, String actorId, int pageSize, Locale locale) throws FileNotFoundException; - OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config, LoggedUser user, int pageSize, Locale locale, Boolean isIntersection) throws FileNotFoundException; + OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config, String actorId, int pageSize, Locale locale, Boolean isIntersection) throws FileNotFoundException; OutputStream buildTaskCsv(List exportTasks, ExportDataConfig config, File outFile) throws FileNotFoundException; diff --git a/src/main/java/com/netgrif/application/engine/history/domain/actorevents/ActorAssignRoleEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/actorevents/ActorAssignRoleEventLog.java new file mode 100644 index 00000000000..804c9c41f3f --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/history/domain/actorevents/ActorAssignRoleEventLog.java @@ -0,0 +1,19 @@ +package com.netgrif.application.engine.history.domain.actorevents; + +import com.netgrif.application.engine.authorization.domain.Role; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@Getter +public class ActorAssignRoleEventLog extends ActorEventLog implements IRolesEvent { + + private final List roles; + + public ActorAssignRoleEventLog(String email, Collection roles) { + super(email); + this.roles = new ArrayList<>(roles); + } +} diff --git a/src/main/java/com/netgrif/application/engine/history/domain/actorevents/ActorEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/actorevents/ActorEventLog.java new file mode 100644 index 00000000000..11a2ad26d4e --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/history/domain/actorevents/ActorEventLog.java @@ -0,0 +1,14 @@ +package com.netgrif.application.engine.history.domain.actorevents; + +import com.netgrif.application.engine.history.domain.baseevent.EventLog; +import lombok.Getter; + +@Getter +public class ActorEventLog extends EventLog implements IActorEventLog { + + private final String email; + + public ActorEventLog(String email) { + this.email = email; + } +} diff --git a/src/main/java/com/netgrif/application/engine/history/domain/userevents/UserEventLogRepository.java b/src/main/java/com/netgrif/application/engine/history/domain/actorevents/ActorEventLogRepository.java similarity index 51% rename from src/main/java/com/netgrif/application/engine/history/domain/userevents/UserEventLogRepository.java rename to src/main/java/com/netgrif/application/engine/history/domain/actorevents/ActorEventLogRepository.java index a9556a94af5..32695533296 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/userevents/UserEventLogRepository.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/actorevents/ActorEventLogRepository.java @@ -1,10 +1,10 @@ -package com.netgrif.application.engine.history.domain.userevents; +package com.netgrif.application.engine.history.domain.actorevents; import org.bson.types.ObjectId; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; @Repository -public interface UserEventLogRepository extends MongoRepository { +public interface ActorEventLogRepository extends MongoRepository { } diff --git a/src/main/java/com/netgrif/application/engine/history/domain/actorevents/ActorRemoveRoleEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/actorevents/ActorRemoveRoleEventLog.java new file mode 100644 index 00000000000..8fcfdf3ffab --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/history/domain/actorevents/ActorRemoveRoleEventLog.java @@ -0,0 +1,19 @@ +package com.netgrif.application.engine.history.domain.actorevents; + +import com.netgrif.application.engine.authorization.domain.Role; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@Getter +public class ActorRemoveRoleEventLog extends ActorEventLog implements IRolesEvent { + + private final List roles; + + public ActorRemoveRoleEventLog(String email, Collection roles) { + super(email); + this.roles = new ArrayList<>(roles); + } +} diff --git a/src/main/java/com/netgrif/application/engine/history/domain/actorevents/IActorEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/actorevents/IActorEventLog.java new file mode 100644 index 00000000000..85934470e9d --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/history/domain/actorevents/IActorEventLog.java @@ -0,0 +1,4 @@ +package com.netgrif.application.engine.history.domain.actorevents; + +public interface IActorEventLog { +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/history/domain/actorevents/IRolesEvent.java b/src/main/java/com/netgrif/application/engine/history/domain/actorevents/IRolesEvent.java new file mode 100644 index 00000000000..e11156073fc --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/history/domain/actorevents/IRolesEvent.java @@ -0,0 +1,4 @@ +package com.netgrif.application.engine.history.domain.actorevents; + +public interface IRolesEvent { +} diff --git a/src/main/java/com/netgrif/application/engine/history/domain/baseevent/EventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/baseevent/EventLog.java index 5242c48a493..ebe45a53595 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/baseevent/EventLog.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/baseevent/EventLog.java @@ -9,20 +9,17 @@ import java.util.List; +@Getter @Document(collection = "eventLogs") public abstract class EventLog { @Id - @Getter protected ObjectId id; - @Getter protected ObjectId triggerId; - @Getter protected EventPhase eventPhase; - @Getter @Setter protected List triggeredEvents; diff --git a/src/main/java/com/netgrif/application/engine/history/domain/dataevents/GetDataEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/dataevents/GetDataEventLog.java index ee92bcbe968..aeea9b81b2b 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/dataevents/GetDataEventLog.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/dataevents/GetDataEventLog.java @@ -1,6 +1,5 @@ package com.netgrif.application.engine.history.domain.dataevents; -import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.history.domain.taskevents.TaskEventLog; import com.netgrif.application.engine.petrinet.domain.events.EventPhase; import com.netgrif.application.engine.workflow.domain.Case; @@ -16,7 +15,7 @@ public GetDataEventLog() { super(); } - public GetDataEventLog(Task task, Case useCase, EventPhase eventPhase, IUser user) { - super(task, useCase, eventPhase, user.getStringId(), user.isImpersonating() ? user.getImpersonated().getStringId() : null); + public GetDataEventLog(Task task, Case useCase, EventPhase eventPhase, String actorId) { + super(task, useCase, eventPhase, actorId, null); } } diff --git a/src/main/java/com/netgrif/application/engine/history/domain/dataevents/SetDataEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/dataevents/SetDataEventLog.java index 2f89f76d819..8aabad308b7 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/dataevents/SetDataEventLog.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/dataevents/SetDataEventLog.java @@ -1,6 +1,5 @@ package com.netgrif.application.engine.history.domain.dataevents; -import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.history.domain.taskevents.TaskEventLog; import com.netgrif.application.engine.petrinet.domain.events.EventPhase; import com.netgrif.application.engine.workflow.domain.Case; @@ -24,8 +23,8 @@ public SetDataEventLog() { super(); } - public SetDataEventLog(Task task, Case useCase, EventPhase eventPhase, DataSet changedFields, IUser user) { - super(task, useCase, eventPhase, user.getStringId(), user.isImpersonating() ? user.getImpersonated().getStringId() : null); + public SetDataEventLog(Task task, Case useCase, EventPhase eventPhase, DataSet changedFields, String actorId) { + super(task, useCase, eventPhase, actorId, null); this.changedFields = changedFields; } } diff --git a/src/main/java/com/netgrif/application/engine/history/domain/identityevents/IIdentityEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/identityevents/IIdentityEventLog.java new file mode 100644 index 00000000000..1e3ad4a406c --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/history/domain/identityevents/IIdentityEventLog.java @@ -0,0 +1,4 @@ +package com.netgrif.application.engine.history.domain.identityevents; + +public interface IIdentityEventLog { +} diff --git a/src/main/java/com/netgrif/application/engine/history/domain/identityevents/IdentityEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/identityevents/IdentityEventLog.java new file mode 100644 index 00000000000..a2e24f63722 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/history/domain/identityevents/IdentityEventLog.java @@ -0,0 +1,14 @@ +package com.netgrif.application.engine.history.domain.identityevents; + +import com.netgrif.application.engine.history.domain.baseevent.EventLog; +import lombok.Getter; + +@Getter +public class IdentityEventLog extends EventLog implements IIdentityEventLog { + + private final String username; + + public IdentityEventLog(String username) { + this.username = username; + } +} diff --git a/src/main/java/com/netgrif/application/engine/history/domain/impersonationevents/ImpersonationEndEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/impersonationevents/ImpersonationEndEventLog.java deleted file mode 100644 index 288070b248e..00000000000 --- a/src/main/java/com/netgrif/application/engine/history/domain/impersonationevents/ImpersonationEndEventLog.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.netgrif.application.engine.history.domain.impersonationevents; - -import lombok.EqualsAndHashCode; -import org.springframework.data.mongodb.core.mapping.Document; - -@Document(collection = "eventLogs") -@EqualsAndHashCode(callSuper = true) -public class ImpersonationEndEventLog extends ImpersonationEventLog { - - public ImpersonationEndEventLog() { - super(); - } - - public ImpersonationEndEventLog(String impersonator, String impersonated) { - super(impersonator, impersonated); - } -} diff --git a/src/main/java/com/netgrif/application/engine/history/domain/impersonationevents/ImpersonationEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/impersonationevents/ImpersonationEventLog.java deleted file mode 100644 index cde6e92d3fc..00000000000 --- a/src/main/java/com/netgrif/application/engine/history/domain/impersonationevents/ImpersonationEventLog.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.netgrif.application.engine.history.domain.impersonationevents; - -import com.netgrif.application.engine.history.domain.baseevent.EventLog; -import lombok.EqualsAndHashCode; -import lombok.Getter; - -@EqualsAndHashCode(callSuper = true) -public abstract class ImpersonationEventLog extends EventLog { - - @Getter - private String impersonator; - - @Getter - private String impersonated; - - public ImpersonationEventLog() { - super(); - } - - public ImpersonationEventLog(String impersonator, String impersonated) { - super(); - this.impersonator = impersonator; - this.impersonated = impersonated; - } -} diff --git a/src/main/java/com/netgrif/application/engine/history/domain/impersonationevents/ImpersonationStartEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/impersonationevents/ImpersonationStartEventLog.java deleted file mode 100644 index 9160f2684f9..00000000000 --- a/src/main/java/com/netgrif/application/engine/history/domain/impersonationevents/ImpersonationStartEventLog.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.netgrif.application.engine.history.domain.impersonationevents; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import org.springframework.data.mongodb.core.mapping.Document; - -import java.util.List; - -@Document(collection = "eventLogs") -@EqualsAndHashCode(callSuper = true) -public class ImpersonationStartEventLog extends ImpersonationEventLog { - - @Getter - private List roles; - - @Getter - private List authorities; - - public ImpersonationStartEventLog() { - super(); - } - - public ImpersonationStartEventLog(String impersonator, String impersonated, List roles, List authorities) { - super(impersonator, impersonated); - this.roles = roles; - this.authorities = authorities; - } -} diff --git a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/AssignTaskEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/AssignTaskEventLog.java index 6c2e3600e73..ab27bb80778 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/AssignTaskEventLog.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/AssignTaskEventLog.java @@ -1,6 +1,5 @@ package com.netgrif.application.engine.history.domain.taskevents; -import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.petrinet.domain.events.EventPhase; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; @@ -16,7 +15,7 @@ public AssignTaskEventLog() { super(); } - public AssignTaskEventLog(Task task, Case useCase, EventPhase eventPhase, IUser user) { - super(task, useCase, eventPhase, user.getStringId(), user.isImpersonating() ? user.getImpersonated().getStringId() : null); + public AssignTaskEventLog(Task task, Case useCase, EventPhase eventPhase, String actorId) { + super(task, useCase, eventPhase, actorId, null); } } diff --git a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/CancelTaskEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/CancelTaskEventLog.java index d68555ab8ad..93208ec60ff 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/CancelTaskEventLog.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/CancelTaskEventLog.java @@ -1,6 +1,5 @@ package com.netgrif.application.engine.history.domain.taskevents; -import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.petrinet.domain.events.EventPhase; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; @@ -15,7 +14,8 @@ public CancelTaskEventLog() { super(); } - public CancelTaskEventLog(Task task, Case useCase, EventPhase eventPhase, IUser user) { - super(task, useCase, eventPhase, user.getStringId(), user.isImpersonating() ? user.getImpersonated().getStringId() : null); + public CancelTaskEventLog(Task task, Case useCase, EventPhase eventPhase, String actorId) { + // todo: release/8.0.0 impersonating + super(task, useCase, eventPhase, actorId, null); } } diff --git a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/DelegateTaskEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/DelegateTaskEventLog.java index 1d3f1411d9d..8aac2aae23d 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/DelegateTaskEventLog.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/DelegateTaskEventLog.java @@ -1,30 +1,12 @@ package com.netgrif.application.engine.history.domain.taskevents; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.petrinet.domain.events.EventPhase; -import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.Task; import lombok.EqualsAndHashCode; -import lombok.Getter; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "eventLogs") @EqualsAndHashCode(callSuper = true) public class DelegateTaskEventLog extends TaskEventLog { - - @Getter - private String delegator; - - @Getter - private String delegate; - public DelegateTaskEventLog() { super(); } - - public DelegateTaskEventLog(Task task, Case useCase, EventPhase eventPhase, IUser delegator, String delegate) { - super(task, useCase, eventPhase, delegator.getStringId(), delegator.isImpersonating() ? delegator.getImpersonated().getStringId() : null); - this.delegator = getUserId(); - this.delegate = delegate; - } } diff --git a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/FinishTaskEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/FinishTaskEventLog.java index 11e3daa6a1b..cbb12bac8e7 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/FinishTaskEventLog.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/FinishTaskEventLog.java @@ -1,6 +1,5 @@ package com.netgrif.application.engine.history.domain.taskevents; -import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.petrinet.domain.events.EventPhase; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; @@ -15,7 +14,8 @@ public FinishTaskEventLog() { super(); } - public FinishTaskEventLog(Task task, Case useCase, EventPhase eventPhase, IUser user) { - super(task, useCase, eventPhase, user.getStringId(), user.isImpersonating() ? user.getImpersonated().getStringId() : null); + public FinishTaskEventLog(Task task, Case useCase, EventPhase eventPhase, String actorId) { + // todo: release/8.0.0 impersonating + super(task, useCase, eventPhase, actorId, null); } } diff --git a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/TaskEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/TaskEventLog.java index 4e0e097cb5d..3ebeb4ce73e 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/TaskEventLog.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/TaskEventLog.java @@ -23,18 +23,18 @@ public abstract class TaskEventLog extends CaseEventLog { private String impersonatorId; @Getter - private String userId; + private String actorId; public TaskEventLog() { super(); } - protected TaskEventLog(Task task, Case useCase, EventPhase eventPhase, String userId, String impersonatorId) { + protected TaskEventLog(Task task, Case useCase, EventPhase eventPhase, String actorId, String impersonatorId) { super(task.getObjectId(), useCase, eventPhase); this.taskId = task.getStringId(); this.taskTitle = task.getTitle().toString(); this.transitionId = task.getTransitionId(); this.impersonatorId = impersonatorId; - this.userId = userId; + this.actorId = actorId; } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/AssignTaskEventLogRepository.java b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/AssignTaskEventLogRepository.java index e53e683fcbc..3de942df466 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/AssignTaskEventLogRepository.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/AssignTaskEventLogRepository.java @@ -11,9 +11,9 @@ @Deprecated(since = "6.3.0") public interface AssignTaskEventLogRepository extends MongoRepository { - List findAllByTaskId(ObjectId taskId); + List findAllByTaskId(String taskId); - List findAllByUserId(String id); + List findAllByActorId(String id); List findAllByCaseId(String caseId); } diff --git a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/CancelTaskEventLogRepository.java b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/CancelTaskEventLogRepository.java index d5ff580a7a6..ea468117b5c 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/CancelTaskEventLogRepository.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/CancelTaskEventLogRepository.java @@ -11,7 +11,7 @@ @Deprecated(since = "6.3.0") public interface CancelTaskEventLogRepository extends MongoRepository { - List findAllByTaskId(ObjectId taskId); + List findAllByTaskId(String taskId); - List findAllByUserId(String id); + List findAllByActorId(String id); } diff --git a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/DelegateTaskEventLogRepository.java b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/DelegateTaskEventLogRepository.java index 0d5244e0fcb..f004fc19dfe 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/DelegateTaskEventLogRepository.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/DelegateTaskEventLogRepository.java @@ -11,7 +11,5 @@ @Deprecated(since = "6.3.0") public interface DelegateTaskEventLogRepository extends MongoRepository { - List findAllByTaskId(ObjectId taskId); - - List findAllByTaskIdAndDelegate(ObjectId taskId, Long delegateId); + List findAllByTaskId(String taskId); } diff --git a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/FinishTaskEventLogRepository.java b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/FinishTaskEventLogRepository.java index 4864e2cc991..8312f786783 100644 --- a/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/FinishTaskEventLogRepository.java +++ b/src/main/java/com/netgrif/application/engine/history/domain/taskevents/repository/FinishTaskEventLogRepository.java @@ -11,9 +11,9 @@ @Deprecated(since = "6.3.0") public interface FinishTaskEventLogRepository extends MongoRepository { - List findAllByTaskId(ObjectId taskId); + List findAllByTaskId(String taskId); - List findAllByUserId(String id); + List findAllByActorId(String id); List findAllByCaseId(String caseId); } diff --git a/src/main/java/com/netgrif/application/engine/history/domain/userevents/AdminActionEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/userevents/AdminActionEventLog.java deleted file mode 100644 index 5704e29156f..00000000000 --- a/src/main/java/com/netgrif/application/engine/history/domain/userevents/AdminActionEventLog.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.netgrif.application.engine.history.domain.userevents; - -import com.netgrif.application.engine.event.events.user.AdminActionEvent; -import lombok.Getter; -import org.springframework.data.annotation.TypeAlias; -import org.springframework.data.mongodb.core.mapping.Document; - -@TypeAlias("adminActionEventLog") -@Document(collection = "eventLogs") -public class AdminActionEventLog extends UserEventLog { - - @Getter - private final String code; - - public AdminActionEventLog(AdminActionEvent event) { - super(event.getUser().getEmail()); - this.code = event.getCode(); - } -} diff --git a/src/main/java/com/netgrif/application/engine/history/domain/userevents/IProcessRolesEvent.java b/src/main/java/com/netgrif/application/engine/history/domain/userevents/IProcessRolesEvent.java deleted file mode 100644 index 0cc2c763137..00000000000 --- a/src/main/java/com/netgrif/application/engine/history/domain/userevents/IProcessRolesEvent.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.netgrif.application.engine.history.domain.userevents; - -public interface IProcessRolesEvent { -} diff --git a/src/main/java/com/netgrif/application/engine/history/domain/userevents/IUserEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/userevents/IUserEventLog.java deleted file mode 100644 index 54baad9100d..00000000000 --- a/src/main/java/com/netgrif/application/engine/history/domain/userevents/IUserEventLog.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.netgrif.application.engine.history.domain.userevents; - -public interface IUserEventLog { -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/history/domain/userevents/UserEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/userevents/UserEventLog.java deleted file mode 100644 index 61e054c9192..00000000000 --- a/src/main/java/com/netgrif/application/engine/history/domain/userevents/UserEventLog.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.netgrif.application.engine.history.domain.userevents; - -import com.netgrif.application.engine.history.domain.baseevent.EventLog; -import lombok.Getter; - -public class UserEventLog extends EventLog implements IUserEventLog { - - @Getter - private final String email; - - public UserEventLog(String email) { - this.email = email; - } -} diff --git a/src/main/java/com/netgrif/application/engine/history/domain/userevents/UserRoleEventLog.java b/src/main/java/com/netgrif/application/engine/history/domain/userevents/UserRoleEventLog.java deleted file mode 100644 index 976173acb27..00000000000 --- a/src/main/java/com/netgrif/application/engine/history/domain/userevents/UserRoleEventLog.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.netgrif.application.engine.history.domain.userevents; - -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import lombok.Getter; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class UserRoleEventLog extends UserEventLog implements IProcessRolesEvent { - - @Getter - private final List roles; - - public UserRoleEventLog(String email, Collection roles) { - super(email); - this.roles = new ArrayList<>(roles); - } -} diff --git a/src/main/java/com/netgrif/application/engine/history/service/listener/ActorEventListener.java b/src/main/java/com/netgrif/application/engine/history/service/listener/ActorEventListener.java new file mode 100644 index 00000000000..b2244a28152 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/history/service/listener/ActorEventListener.java @@ -0,0 +1,29 @@ +package com.netgrif.application.engine.history.service.listener; + +import com.netgrif.application.engine.event.events.authorization.ActorAssignRoleEvent; +import com.netgrif.application.engine.event.events.authorization.ActorRemoveRoleEvent; +import com.netgrif.application.engine.history.domain.baseevent.repository.EventLogRepository; +import com.netgrif.application.engine.history.domain.actorevents.ActorRemoveRoleEventLog; +import com.netgrif.application.engine.history.domain.actorevents.ActorAssignRoleEventLog; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +@Component +public class ActorEventListener { + + private final EventLogRepository repository; + + public ActorEventListener(EventLogRepository repository) { + this.repository = repository; + } + + @EventListener + public void onActorRoleChangeEvent(ActorAssignRoleEvent event) { + repository.save(new ActorAssignRoleEventLog(event.getActor().getName(), event.getRoles())); + } + + @EventListener + public void onActorRoleChangeEvent(ActorRemoveRoleEvent event) { + repository.save(new ActorRemoveRoleEventLog(event.getActor().getName(), event.getRoles())); + } +} diff --git a/src/main/java/com/netgrif/application/engine/history/service/listener/IdentityEventListener.java b/src/main/java/com/netgrif/application/engine/history/service/listener/IdentityEventListener.java new file mode 100644 index 00000000000..90b68e5c84f --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/history/service/listener/IdentityEventListener.java @@ -0,0 +1,32 @@ +package com.netgrif.application.engine.history.service.listener; + +import com.netgrif.application.engine.event.events.authentication.IdentityLoginEvent; +import com.netgrif.application.engine.event.events.authentication.IdentityLogoutEvent; +import com.netgrif.application.engine.event.events.authentication.IdentityRegistrationEvent; +import com.netgrif.application.engine.history.domain.baseevent.repository.EventLogRepository; +import com.netgrif.application.engine.history.domain.identityevents.IdentityEventLog; +import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class IdentityEventListener { + + private final EventLogRepository repository; + + @EventListener + public void onIdentityLoginEvent(IdentityLoginEvent event) { + // todo: release/8.0.0 + } + + @EventListener + public void onIdentityLogoutEvent(IdentityLogoutEvent event) { + // todo: release/8.0.0 + } + + @EventListener + public void onIdentityRegistrationEvent(IdentityRegistrationEvent event) { + repository.save(new IdentityEventLog(event.getIdentity().getUsername())); + } +} diff --git a/src/main/java/com/netgrif/application/engine/history/service/listener/UserEventListener.java b/src/main/java/com/netgrif/application/engine/history/service/listener/UserEventListener.java deleted file mode 100644 index ba56de40fd5..00000000000 --- a/src/main/java/com/netgrif/application/engine/history/service/listener/UserEventListener.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.netgrif.application.engine.history.service.listener; - -import com.netgrif.application.engine.event.events.user.*; -import com.netgrif.application.engine.history.domain.baseevent.repository.EventLogRepository; -import com.netgrif.application.engine.history.domain.userevents.AdminActionEventLog; -import com.netgrif.application.engine.history.domain.userevents.UserEventLog; -import com.netgrif.application.engine.history.domain.userevents.UserRoleEventLog; -import org.springframework.context.event.EventListener; -import org.springframework.stereotype.Component; - -@Component -public class UserEventListener { - - private final EventLogRepository repository; - - public UserEventListener(EventLogRepository repository) { - this.repository = repository; - } - - @EventListener - public void onUserLoginEvent(UserLoginEvent event) { - repository.save(new UserEventLog(event.getUser().getUsername())); - } - - @EventListener - public void onUserLogoutEvent(UserLogoutEvent event) { - repository.save(new UserEventLog(event.getUser().getUsername())); - } - - @EventListener - public void onUserRegistrationEvent(UserRegistrationEvent event) { - repository.save(new UserEventLog(event.getUser().getUsername())); - } - - @EventListener - public void onUserRoleChangeEvent(UserRoleChangeEvent event) { - repository.save(new UserRoleEventLog(event.getUser().getUsername(), event.getRoles())); - } - - @EventListener - public void onAdminActionEvent(AdminActionEvent event) { - repository.save(new AdminActionEventLog(event)); - } -} diff --git a/src/main/java/com/netgrif/application/engine/history/web/HistoryController.java b/src/main/java/com/netgrif/application/engine/history/web/HistoryController.java index 7a4324cb602..5e2c523284e 100644 --- a/src/main/java/com/netgrif/application/engine/history/web/HistoryController.java +++ b/src/main/java/com/netgrif/application/engine/history/web/HistoryController.java @@ -12,5 +12,5 @@ matchIfMissing = true ) public class HistoryController { - + // TODO: release/8.0.0 keep? } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/impersonation/domain/Impersonator.java b/src/main/java/com/netgrif/application/engine/impersonation/domain/Impersonator.java deleted file mode 100644 index 618fc27f4e6..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/domain/Impersonator.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.netgrif.application.engine.impersonation.domain; - - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.springframework.data.annotation.Id; -import org.springframework.data.redis.core.RedisHash; -import org.springframework.data.redis.core.index.Indexed; - -import java.io.Serializable; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -@Data -@NoArgsConstructor -@AllArgsConstructor -@RedisHash(value = "#{@impersonatorRedisHash}") -public class Impersonator implements Serializable { - - @Id - protected String impersonatorId; - - @Indexed - protected String impersonatedId; - - @Indexed - protected List configIds = new ArrayList<>(); - - protected LocalDateTime impersonatingSince; - protected LocalDateTime impersonatingUntil; -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/domain/repository/ImpersonatorRepository.java b/src/main/java/com/netgrif/application/engine/impersonation/domain/repository/ImpersonatorRepository.java deleted file mode 100644 index 5bdbc7465ca..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/domain/repository/ImpersonatorRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.netgrif.application.engine.impersonation.domain.repository; - -import com.netgrif.application.engine.impersonation.domain.Impersonator; -import org.springframework.data.repository.CrudRepository; -import org.springframework.stereotype.Repository; - -import java.util.Optional; - -@Repository -public interface ImpersonatorRepository extends CrudRepository { - - Optional findByImpersonatedId(String impersonatedId); - -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/exceptions/IllegalImpersonationAttemptException.java b/src/main/java/com/netgrif/application/engine/impersonation/exceptions/IllegalImpersonationAttemptException.java deleted file mode 100644 index f9ed0e568b8..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/exceptions/IllegalImpersonationAttemptException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.netgrif.application.engine.impersonation.exceptions; - -import com.netgrif.application.engine.auth.domain.LoggedUser; - -public class IllegalImpersonationAttemptException extends Exception { - - public IllegalImpersonationAttemptException(LoggedUser loggedUser, String id) { - super(loggedUser.getFullName() + " cannot impersonate user or config with ID " + id); - } - - public IllegalImpersonationAttemptException(String message) { - super(message); - } -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/exceptions/ImpersonatedUserHasSessionException.java b/src/main/java/com/netgrif/application/engine/impersonation/exceptions/ImpersonatedUserHasSessionException.java deleted file mode 100644 index c36f160e433..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/exceptions/ImpersonatedUserHasSessionException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.netgrif.application.engine.impersonation.exceptions; - -import com.netgrif.application.engine.auth.domain.LoggedUser; -import lombok.Getter; - -public class ImpersonatedUserHasSessionException extends Exception { - - @Getter - private final boolean isImpersonated; - - public ImpersonatedUserHasSessionException(LoggedUser impersonatedLogged, boolean isImpersonated) { - super(impersonatedLogged.getFullName() + " has an existing session!"); - this.isImpersonated = isImpersonated; - } -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationAuthorizationService.java b/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationAuthorizationService.java deleted file mode 100644 index cfbfe9cb4bd..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationAuthorizationService.java +++ /dev/null @@ -1,201 +0,0 @@ -package com.netgrif.application.engine.impersonation.service; - -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.configuration.properties.ImpersonationProperties; -import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; -import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationAuthorizationService; -import com.netgrif.application.engine.petrinet.domain.dataset.BooleanField; -import com.netgrif.application.engine.petrinet.domain.dataset.DateTimeField; -import com.netgrif.application.engine.petrinet.domain.dataset.MultichoiceMapField; -import com.netgrif.application.engine.petrinet.domain.dataset.UserFieldValue; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; -import com.netgrif.application.engine.utils.DateUtils; -import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; - -import java.time.LocalDateTime; -import java.util.*; -import java.util.stream.Collectors; - -import static com.netgrif.application.engine.startup.ImpersonationRunner.IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER; - -@Service -public class ImpersonationAuthorizationService implements IImpersonationAuthorizationService { - - @Autowired - protected ImpersonationProperties properties; - - @Autowired - protected IUserService userService; - - @Autowired - protected IElasticCaseService elasticCaseService; - - @Autowired - protected IAuthorityService authorityService; - - @Autowired - protected IWorkflowService workflowService; - - @Autowired - protected IProcessRoleService processRoleService; - - @Override - public Page getConfiguredImpersonationUsers(String query, LoggedUser impersonator, Pageable pageable) { - if (impersonator.isAdmin()) { - return userService.searchAllCoMembers(query, impersonator, pageable); - - } else { - Page cases = searchConfigs(impersonator.getId(), pageable); - List users = cases.getContent().stream() - .map(c -> ((UserFieldValue) c.getDataSet().get("impersonated").getRawValue()).getId()) - .distinct() - .map(id -> userService.findById(id)) - .collect(Collectors.toList()); - return new PageImpl<>(users, pageable, cases.getTotalElements()); - } - } - - @Override - public boolean canImpersonate(LoggedUser impersonator, String configId) { - Case config = getConfig(configId); - return isValidAndContainsUser(config, impersonator.getId()); - } - - @Override - public boolean canImpersonateUser(LoggedUser impersonator, String userId) { - IUser impersonated = userService.findById(userId); - return impersonator.isAdmin() || !searchConfigs(impersonator.getId(), impersonated.getStringId()).isEmpty(); - } - - @Override - public Page searchConfigs(String impersonatorId, Pageable pageable) { - return findCases(makeRequest(impersonatorId, null), pageable); - } - - @Override - public List searchConfigs(String impersonatorId, String impersonatedId) { - Page cases = findCases(makeRequest(impersonatorId, impersonatedId), PageRequest.of(0, properties.getConfigsPerUser())); - return cases.getContent(); - } - - @Override - public List getAuthorities(List configs, IUser impersonated) { - if (configs.isEmpty()) { - return new ArrayList<>(); - } - Set authIds = extractSetFromField(configs, "impersonated_authorities"); - return authorityService.findAllByIds(new ArrayList<>(authIds)).stream() - .filter(configAuth -> impersonated.getAuthorities().stream().anyMatch(userAuth -> userAuth.getStringId().equals(configAuth.getStringId()))) - .collect(Collectors.toList()); - } - - @Override - public List getRoles(List configs, IUser impersonated) { - List impersonatedRoles = new ArrayList<>(); - impersonatedRoles.add(processRoleService.defaultRole()); - if (configs.isEmpty()) { - return impersonatedRoles; - } - Set roleIds = extractSetFromField(configs, "impersonated_roles"); - impersonatedRoles.addAll((processRoleService.findByIds(roleIds)).stream() - .filter(configRole -> impersonated.getProcessRoles().stream().anyMatch(userRole -> userRole.getStringId().equals(configRole.getStringId()))) - .collect(Collectors.toList())); - return impersonatedRoles; - } - - @Override - public Case getConfig(String configId) { - return workflowService.findOne(configId); - } - - @Override - public String getImpersonatedUserId(Case config) { - return ((UserFieldValue) config.getDataSet().get("impersonated").getRawValue()).getId(); - } - - @Override - public LocalDateTime getValidUntil(Case config) { - return ((DateTimeField) config.getDataSet().get("valid_to")).getRawValue(); - } - - @Override - public LocalDateTime getValidFrom(Case config) { - return ((DateTimeField) config.getDataSet().get("valid_from")).getRawValue(); - } - - protected CaseSearchRequest makeRequest(String impersonatorId, String impersonatedId) { - CaseSearchRequest request = new CaseSearchRequest(); - List queries = new ArrayList<>(); - request.process = Collections.singletonList(new CaseSearchRequest.PetriNet(IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER)); - queries.add("(dataSet.impersonators.keyValue:" + impersonatorId + ")"); - queries.add("(dataSet.is_active.booleanValue:true)"); - queries.addAll(validityQueries()); - if (impersonatedId != null) { - queries.add("(dataSet.impersonated.userIdValue.keyword:" + impersonatedId + ")"); - } - request.query = combineQueries(queries); - return request; - } - - protected List validityQueries() { - List queries = new ArrayList<>(); - queries.add("((!(_exists_:dataSet.valid_from.timestampValue)) OR (dataSet.valid_from.timestampValue:<" + DateUtils.localDateTimeToDate(LocalDateTime.now()).getTime() + "))"); - queries.add("((!(_exists_:dataSet.valid_to.timestampValue)) OR (dataSet.valid_to.timestampValue:>" + DateUtils.localDateTimeToDate(LocalDateTime.now()).getTime() + "))"); - return queries; - } - - protected String combineQueries(List queries) { - return "(" + String.join(" AND ", queries) + ")"; - } - - protected Page findCases(CaseSearchRequest request, Pageable pageable) { - return elasticCaseService.search(Collections.singletonList(request), userService.getSystem().transformToLoggedUser(), pageable, Locale.getDefault(), false); - } - - protected boolean isValidAndContainsUser(Case config, String id) { - MultichoiceMapField impersonators = (MultichoiceMapField) config.getDataSet().get("impersonators"); - BooleanField isActive = (BooleanField) config.getDataSet().get("is_active"); - Set value = impersonators.getRawValue(); - if (value == null) { - return false; - } - LocalDateTime now = LocalDateTime.now(); - return (value).contains(id) && - (isActive.getRawValue() != null && isActive.getRawValue()) && - validateTime(getValidFrom(config), now) && - validateTime(now, getValidUntil(config)); - - } - - protected boolean validateTime(LocalDateTime first, LocalDateTime second) { - if (first == null || second == null) { - return true; - } - return first.isBefore(second) || first.equals(second); - } - - protected Set extractSetFromField(List cases, String fieldId) { - Set allStrings = new HashSet<>(); - for (Case c : cases) { - Set rawValue = ((MultichoiceMapField) c.getDataSet().get(fieldId)).getRawValue(); - if (rawValue == null) { - continue; - } - allStrings.addAll(rawValue); - } - return allStrings; - } -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationService.java b/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationService.java deleted file mode 100644 index 31be0c377a8..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationService.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.netgrif.application.engine.impersonation.service; - -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.configuration.properties.ImpersonationProperties; -import com.netgrif.application.engine.history.domain.impersonationevents.ImpersonationEndEventLog; -import com.netgrif.application.engine.history.domain.impersonationevents.ImpersonationStartEventLog; -import com.netgrif.application.engine.history.service.IHistoryService; -import com.netgrif.application.engine.impersonation.domain.Impersonator; -import com.netgrif.application.engine.impersonation.domain.repository.ImpersonatorRepository; -import com.netgrif.application.engine.impersonation.exceptions.ImpersonatedUserHasSessionException; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationAuthorizationService; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationSessionService; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.security.service.ISecurityContextService; -import com.netgrif.application.engine.workflow.domain.Case; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.time.LocalDateTime; -import java.util.*; -import java.util.stream.Collectors; - -@Slf4j -@Service -public class ImpersonationService implements IImpersonationService { - - @Autowired - protected ImpersonationProperties properties; - - @Autowired - protected IUserService userService; - - @Autowired - protected IHistoryService historyService; - - @Autowired - protected IImpersonationSessionService sessionService; - - @Autowired - protected ISecurityContextService securityContextService; - - @Autowired - protected ImpersonatorRepository impersonatorRepository; - - @Autowired - protected IImpersonationAuthorizationService impersonationAuthorizationService; - - @Override - public LoggedUser impersonateUser(String impersonatedId) throws ImpersonatedUserHasSessionException { - if (!properties.isEnabled()) { - throw new IllegalArgumentException("Impersonation is not enabled in app properties"); - } - LoggedUser loggedUser = userService.getLoggedUser().transformToLoggedUser(); - IUser impersonated = userService.findById(impersonatedId); - - List configs = impersonationAuthorizationService.searchConfigs(loggedUser.getId(), impersonated.getStringId()); - LoggedUser impersonatedLogged = applyRolesAndAuthorities(impersonated, loggedUser.getId(), configs).transformToLoggedUser(); - - return doImpersonate(loggedUser, impersonatedLogged, configs); - } - - @Override - public LoggedUser impersonateByConfig(String configId) throws ImpersonatedUserHasSessionException { - if (!properties.isEnabled()) { - throw new IllegalArgumentException("Impersonation is not enabled in app properties"); - } - Case config = impersonationAuthorizationService.getConfig(configId); - LoggedUser loggedUser = userService.getLoggedUser().transformToLoggedUser(); - IUser impersonated = userService.findById(impersonationAuthorizationService.getImpersonatedUserId(config)); - - LoggedUser impersonatedLogged = applyRolesAndAuthorities(impersonated, loggedUser.getId(), Collections.singletonList(config)).transformToLoggedUser(); - return doImpersonate(loggedUser, impersonatedLogged, Collections.singletonList(config)); - } - - protected LoggedUser doImpersonate(LoggedUser loggedUser, LoggedUser impersonatedLogged, List configs) throws ImpersonatedUserHasSessionException { - if (sessionService.existsSession(impersonatedLogged.getUsername())) { - throw new ImpersonatedUserHasSessionException(impersonatedLogged, false); - - } else if (sessionService.isImpersonated(impersonatedLogged.getId())) { - throw new ImpersonatedUserHasSessionException(impersonatedLogged, true); - } - updateImpersonatedId(loggedUser, impersonatedLogged.getId(), configs); - loggedUser.impersonate(impersonatedLogged); - securityContextService.saveToken(loggedUser.getId()); - securityContextService.reloadSecurityContext(loggedUser); - log.info(loggedUser.getFullName() + " has just impersonated user " + impersonatedLogged.getFullName()); - historyService.save( - new ImpersonationStartEventLog(loggedUser.getId(), impersonatedLogged.getId(), - new ArrayList<>(impersonatedLogged.getProcessRoles()), - impersonatedLogged.getAuthorities().stream().map(au -> ((Authority) au).getStringId()).collect(Collectors.toList())) - ); - return loggedUser; - } - - @Override - public Optional findImpersonator(String impersonatorId) { - return impersonatorRepository.findById(impersonatorId); - } - - @Override - public void removeImpersonatorByImpersonated(String impersonatedId) { - impersonatorRepository.findByImpersonatedId(impersonatedId).ifPresent(impersonatorRepository::delete); - } - - @Override - public void removeImpersonator(String impersonatorId) { - impersonatorRepository.deleteById(impersonatorId); - } - - @Override - public LoggedUser endImpersonation() { - return endImpersonation(userService.getLoggedUserFromContext()); - } - - @Override - public LoggedUser endImpersonation(LoggedUser impersonator) { - LoggedUser impersonated = impersonator.getImpersonated(); - removeImpersonator(impersonator.getId()); - impersonator.clearImpersonated(); - log.info(impersonator.getFullName() + " has stopped impersonating user " + impersonated.getFullName()); - securityContextService.saveToken(impersonator.getId()); - securityContextService.reloadSecurityContext(impersonator); - historyService.save(new ImpersonationEndEventLog(impersonator.getId(), impersonated.getId())); - return impersonator; - } - - @Override - public void onSessionDestroy(LoggedUser impersonator) { - removeImpersonator(impersonator.getId()); - log.info(impersonator.getFullName() + " has logged out and stopped impersonating user " + impersonator.getImpersonated().getFullName()); - historyService.save(new ImpersonationEndEventLog(impersonator.getId(), impersonator.getImpersonated().getId())); - } - - @Override - public IUser reloadImpersonatedUserRoles(IUser impersonated, String impersonatorId) { - Optional context = impersonatorRepository.findByImpersonatedId(impersonated.getStringId()); - if (context.isPresent()) { - List configs = context.get().getConfigIds().stream() - .map(id -> impersonationAuthorizationService.getConfig(id)) - .collect(Collectors.toList()); - return applyRolesAndAuthorities(impersonated, impersonatorId, configs); - } - return impersonated; - } - - @Override - public IUser applyRolesAndAuthorities(IUser impersonated, String impersonatorId, List configs) { - if (userService.findById(impersonatorId).transformToLoggedUser().isAdmin()) { - return impersonated; - } - List authorities = impersonationAuthorizationService.getAuthorities(configs, impersonated); - List roles = impersonationAuthorizationService.getRoles(configs, impersonated); - - impersonated.setAuthorities(new HashSet<>(authorities)); - impersonated.setProcessRoles(new HashSet<>(roles)); - - return impersonated; - } - - protected void updateImpersonatedId(LoggedUser loggedUser, String id, List configs) { - Map configTimeMap = new HashMap<>(); - configs.forEach((config) -> configTimeMap.put(config, getConfigValidToTime(config))); - Optional> earliestEndingConfig = configTimeMap - .entrySet().stream() - .filter(it -> it.getValue() != null) - .min(Map.Entry.comparingByValue()); - updateImpersonatedId(loggedUser, id, configs, earliestEndingConfig.map(Map.Entry::getValue).orElse(null)); - } - - protected void updateImpersonatedId(LoggedUser loggedUser, String id, List configs, LocalDateTime validUntil) { - removeImpersonator(loggedUser.getId()); - impersonatorRepository.save(new Impersonator(loggedUser.getId(), id, - configs.stream().map(Case::getStringId).collect(Collectors.toList()), - LocalDateTime.now(), validUntil)); - } - - protected LocalDateTime getConfigValidToTime(Case config) { - LocalDateTime limitTime = null; - if (config != null) { - limitTime = impersonationAuthorizationService.getValidUntil(config); - } - return limitTime; - } -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationSessionService.java b/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationSessionService.java deleted file mode 100644 index 73dbb736fd4..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationSessionService.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.netgrif.application.engine.impersonation.service; - -import com.netgrif.application.engine.impersonation.domain.repository.ImpersonatorRepository; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationSessionService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; -import org.springframework.session.FindByIndexNameSessionRepository; -import org.springframework.session.Session; -import org.springframework.session.security.SpringSessionBackedSessionRegistry; -import org.springframework.stereotype.Service; - -import java.util.Collection; - -@Service -public class ImpersonationSessionService implements IImpersonationSessionService { - - protected FindByIndexNameSessionRepository sessions; - protected SpringSessionBackedSessionRegistry registry; - protected ImpersonatorRepository impersonatorRepository; - - @Override - public boolean existsSession(String username) { - Collection usersSessions = this.sessions.findByPrincipalName(username).values(); - return usersSessions.stream().anyMatch(session -> !registry.getSessionInformation(session.getId()).isExpired()); - } - - @Override - public boolean isImpersonated(String userId) { - return impersonatorRepository.findByImpersonatedId(userId).isPresent(); - } - - @Autowired - @Lazy - public void setSessions(FindByIndexNameSessionRepository sessions) { - this.sessions = sessions; - } - - @Autowired - @Lazy - public void setRegistry(SpringSessionBackedSessionRegistry registry) { - this.registry = registry; - } - - @Autowired - @Lazy - public void setImpersonatorRepository(ImpersonatorRepository impersonatorRepository) { - this.impersonatorRepository = impersonatorRepository; - } -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationAuthorizationService.java b/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationAuthorizationService.java deleted file mode 100644 index aba190eb7ba..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationAuthorizationService.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.netgrif.application.engine.impersonation.service.interfaces; - -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.workflow.domain.Case; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -import java.time.LocalDateTime; -import java.util.List; - -public interface IImpersonationAuthorizationService { - - Page getConfiguredImpersonationUsers(String query, LoggedUser impersonator, Pageable pageable); - - boolean canImpersonate(LoggedUser loggedUser, String configId); - - boolean canImpersonateUser(LoggedUser impersonator, String userId); - - Page searchConfigs(String impersonatorId, Pageable pageable); - - List searchConfigs(String impersonatorId, String impersonatedId); - - List getAuthorities(List configs, IUser impersonated); - - List getRoles(List configs, IUser impersonated); - - Case getConfig(String configId); - - String getImpersonatedUserId(Case config); - - LocalDateTime getValidUntil(Case config); - - LocalDateTime getValidFrom(Case config); -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationService.java b/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationService.java deleted file mode 100644 index 278afe337a3..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationService.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.netgrif.application.engine.impersonation.service.interfaces; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.impersonation.domain.Impersonator; -import com.netgrif.application.engine.impersonation.exceptions.ImpersonatedUserHasSessionException; -import com.netgrif.application.engine.workflow.domain.Case; - -import java.util.List; -import java.util.Optional; - -public interface IImpersonationService { - - LoggedUser impersonateUser(String impersonatedId) throws ImpersonatedUserHasSessionException; - - LoggedUser impersonateByConfig(String configId) throws ImpersonatedUserHasSessionException; - - Optional findImpersonator(String impersonatorId); - - void removeImpersonatorByImpersonated(String impersonatedId); - - void removeImpersonator(String impersonatorId); - - LoggedUser endImpersonation(); - - LoggedUser endImpersonation(LoggedUser impersonator); - - void onSessionDestroy(LoggedUser impersonator); - - IUser reloadImpersonatedUserRoles(IUser impersonated, String impersonatorId); - - IUser applyRolesAndAuthorities(IUser impersonated, String impersonatorId, List configs); -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationSessionService.java b/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationSessionService.java deleted file mode 100644 index c28dc266758..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationSessionService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.netgrif.application.engine.impersonation.service.interfaces; - -public interface IImpersonationSessionService { - boolean existsSession(String username); - - boolean isImpersonated(String userId); -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/web/ImpersonationController.java b/src/main/java/com/netgrif/application/engine/impersonation/web/ImpersonationController.java deleted file mode 100644 index 68b6f7dde93..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/web/ImpersonationController.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.netgrif.application.engine.impersonation.web; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.auth.web.responsebodies.User; -import com.netgrif.application.engine.auth.web.responsebodies.UserResource; -import com.netgrif.application.engine.auth.web.responsebodies.UserResourceAssembler; -import com.netgrif.application.engine.impersonation.exceptions.IllegalImpersonationAttemptException; -import com.netgrif.application.engine.impersonation.exceptions.ImpersonatedUserHasSessionException; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationAuthorizationService; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService; -import com.netgrif.application.engine.impersonation.web.requestbodies.SearchRequest; -import com.netgrif.application.engine.workflow.web.responsebodies.ResourceLinkAssembler; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.web.PagedResourcesAssembler; -import org.springframework.hateoas.Link; -import org.springframework.hateoas.MediaTypes; -import org.springframework.hateoas.PagedModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; -import org.springframework.http.MediaType; -import org.springframework.security.core.Authentication; -import org.springframework.web.bind.annotation.*; - -import javax.inject.Provider; -import java.util.Locale; - -@RestController -@RequestMapping("/api/impersonate") -@ConditionalOnProperty( - value = "nae.impersonation.web.enabled", - havingValue = "true", - matchIfMissing = true -) -@Tag(name = "Impersonation") -public class ImpersonationController { - - @Autowired - protected IImpersonationService impersonationService; - - @Autowired - protected IImpersonationAuthorizationService impersonationAuthorizationService; - - @Autowired - protected IUserService userService; - - @Autowired - protected Provider userResourceAssemblerProvider; - - protected UserResourceAssembler getUserResourceAssembler(String selfRel) { - UserResourceAssembler result = userResourceAssemblerProvider.get(); - result.initialize(selfRel); - return result; - } - - @Operation(summary = "Search impersonable users", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public PagedModel getImpersonationUserOptions(@RequestBody SearchRequest request, Pageable pageable, PagedResourcesAssembler assembler, Authentication auth, Locale locale) { - LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); - Page page = impersonationAuthorizationService.getConfiguredImpersonationUsers(request.getQuery(), loggedUser, pageable); - Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(ImpersonationController.class) - .getImpersonationUserOptions(request, pageable, assembler, auth, locale)).withRel("all"); - PagedModel resources = assembler.toModel(page, getUserResourceAssembler("all"), selfLink); - ResourceLinkAssembler.addLinks(resources, IUser.class, selfLink.getRel().toString()); - return resources; - } - - @Operation(summary = "Impersonate user through a specific configuration", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping("/config/{id}") - public UserResource impersonateByConfig(@PathVariable("id") String configId, Locale locale) throws IllegalImpersonationAttemptException, ImpersonatedUserHasSessionException { - LoggedUser loggedUser = userService.getLoggedUser().transformToLoggedUser(); - if (!impersonationAuthorizationService.canImpersonate(loggedUser, configId)) { - throw new IllegalImpersonationAttemptException(loggedUser, configId); - } - loggedUser = impersonationService.impersonateByConfig(configId); - return new UserResource(new User(loggedUser.transformToUser()), ""); - } - - @Operation(summary = "Impersonate user directly by id", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping("/user/{id}") - public UserResource impersonateUser(@PathVariable("id") String userId, Locale locale) throws IllegalImpersonationAttemptException, ImpersonatedUserHasSessionException { - LoggedUser loggedUser = userService.getLoggedUser().transformToLoggedUser(); - if (!impersonationAuthorizationService.canImpersonateUser(loggedUser, userId)) { - throw new IllegalImpersonationAttemptException(loggedUser, userId); - } - loggedUser = impersonationService.impersonateUser(userId); - return new UserResource(new User(loggedUser.transformToUser()), ""); - } - - @Operation(summary = "Stop impersonating currently impersonated user", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping("/clear") - public UserResource endImpersonation(Locale locale) { - LoggedUser loggedUser = impersonationService.endImpersonation(); - return new UserResource(new User(loggedUser.transformToUser()), ""); - } - -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/web/ImpersonationControllerAdvice.java b/src/main/java/com/netgrif/application/engine/impersonation/web/ImpersonationControllerAdvice.java deleted file mode 100644 index 61bda7893ff..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/web/ImpersonationControllerAdvice.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.netgrif.application.engine.impersonation.web; - -import com.netgrif.application.engine.impersonation.exceptions.IllegalImpersonationAttemptException; -import com.netgrif.application.engine.impersonation.exceptions.ImpersonatedUserHasSessionException; -import com.netgrif.application.engine.impersonation.web.responsebodies.ImpersonationNotAvailableResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -@Slf4j -@RestControllerAdvice(assignableTypes = ImpersonationController.class) -public class ImpersonationControllerAdvice { - - @ExceptionHandler - public ResponseEntity handleException(IllegalImpersonationAttemptException ex) { - log.error("Illegal attempt at impersonation", ex); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } - - @ExceptionHandler - @ResponseStatus(HttpStatus.BAD_REQUEST) - public ImpersonationNotAvailableResponse handleException(ImpersonatedUserHasSessionException ex) { - log.error("User is already logged", ex); - return new ImpersonationNotAvailableResponse(ex.isImpersonated()); - } - -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/web/requestbodies/SearchRequest.java b/src/main/java/com/netgrif/application/engine/impersonation/web/requestbodies/SearchRequest.java deleted file mode 100644 index 84f83785447..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/web/requestbodies/SearchRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.netgrif.application.engine.impersonation.web.requestbodies; - -import lombok.Getter; -import lombok.Setter; - -public class SearchRequest { - - @Setter - @Getter - protected String query; - - public SearchRequest() { - } - - public SearchRequest(String query) { - this.query = query; - } -} diff --git a/src/main/java/com/netgrif/application/engine/impersonation/web/responsebodies/ImpersonationNotAvailableResponse.java b/src/main/java/com/netgrif/application/engine/impersonation/web/responsebodies/ImpersonationNotAvailableResponse.java deleted file mode 100644 index ab670d644f3..00000000000 --- a/src/main/java/com/netgrif/application/engine/impersonation/web/responsebodies/ImpersonationNotAvailableResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.netgrif.application.engine.impersonation.web.responsebodies; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class ImpersonationNotAvailableResponse { - - private boolean alreadyImpersonated; - - -} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/AllDataConfiguration.java b/src/main/java/com/netgrif/application/engine/importer/service/AllDataConfiguration.java index f85acda01a1..31aebe6bba0 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/AllDataConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/AllDataConfiguration.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.importer.service; -import com.netgrif.application.engine.importer.model.Transition; +import com.netgrif.application.engine.importer.model.DataRef; +import com.netgrif.application.engine.importer.model.DataRefLogic; import lombok.Data; import org.springframework.stereotype.Component; @@ -8,7 +9,37 @@ @Data public class AllDataConfiguration { - private Transition allData; + private com.netgrif.application.engine.importer.model.Transition allData; // TODO: release/8.0.0 implement logic of creating all data transition here, move from importer + public com.netgrif.application.engine.importer.model.Transition createAllDataTransition(com.netgrif.application.engine.importer.model.Process document) { + com.netgrif.application.engine.importer.model.Transition allDataConfig = this.getAllData(); + if (document.getTransition().stream().anyMatch(transition -> allDataConfig.getId().equals(transition.getId()))) { + return null; + } + com.netgrif.application.engine.importer.model.Transition allDataTransition = new com.netgrif.application.engine.importer.model.Transition(); + allDataTransition.setId(allDataConfig.getId()); + allDataTransition.setX(allDataConfig.getX()); + allDataTransition.setY(allDataConfig.getY()); + allDataTransition.setTitle(allDataConfig.getTitle()); + allDataTransition.setIcon(allDataConfig.getIcon()); + allDataTransition.setAssignPolicy(allDataConfig.getAssignPolicy()); + allDataTransition.setFinishPolicy(allDataConfig.getFinishPolicy()); + com.netgrif.application.engine.importer.model.GridContainer gridContainer = new com.netgrif.application.engine.importer.model.GridContainer(); + gridContainer.setId(allDataConfig.getGrid().getId()); + gridContainer.setProperties(allDataConfig.getGrid().getProperties()); + // TODO: NAE-1858: all properties + for (com.netgrif.application.engine.importer.model.Data field : document.getData()) { + com.netgrif.application.engine.importer.model.GridItem gridItem = new com.netgrif.application.engine.importer.model.GridItem(); + DataRef dataRef = new DataRef(); + dataRef.setId(field.getId()); + DataRefLogic logic = new DataRefLogic(); + logic.setBehavior(com.netgrif.application.engine.importer.model.Behavior.EDITABLE); + dataRef.setLogic(logic); + gridItem.setDataRef(dataRef); + gridContainer.getItem().add(gridItem); + } + allDataTransition.setGrid(gridContainer); + return allDataTransition; + } } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/ArcImporter.java b/src/main/java/com/netgrif/application/engine/importer/service/ArcImporter.java new file mode 100644 index 00000000000..0f199c673c1 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/ArcImporter.java @@ -0,0 +1,71 @@ +package com.netgrif.application.engine.importer.service; + +import com.netgrif.application.engine.importer.model.ArcType; +import com.netgrif.application.engine.importer.model.Expression; +import com.netgrif.application.engine.petrinet.domain.Node; +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.petrinet.domain.arcs.*; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +@Component +public final class ArcImporter { + + private final Map> ptArcFactory; + private final Map> tpArcFactory; + + public ArcImporter() { + ptArcFactory = new HashMap<>(); + ptArcFactory.put(ArcType.REGULAR, RegularPTArc::new); + ptArcFactory.put(ArcType.RESET, ResetArc::new); + ptArcFactory.put(ArcType.INHIBITOR, InhibitorArc::new); + ptArcFactory.put(ArcType.READ, ReadArc::new); + tpArcFactory = new HashMap<>(); + tpArcFactory.put(ArcType.REGULAR, RegularTPArc::new); + } + + public Arc getArc(com.netgrif.application.engine.importer.model.Arc importArc, Importer importer) { + Arc arc; + if (importer.isInputArc(importArc)) { + arc = getInputArc(importArc, importer); + } else { + arc = getOutputArc(importArc, importer); + } + arc.setImportId(importArc.getId()); + arc.setMultiplicityExpression(createMultiplicity(importArc.getMultiplicity(), importer)); + importer.createProperties(importArc.getProperties(), arc.getProperties()); + return arc; + } + + public TPArc getOutputArc(com.netgrif.application.engine.importer.model.Arc importArc, Importer importer) throws IllegalArgumentException { + TPArc arc = tpArcFactory.get(importArc.getType()).get(); + arc.setSource(importer.getTransition(importArc.getSourceId())); + arc.setDestination(importer.getPlace(importArc.getDestinationId())); + return arc; + } + + public PTArc getInputArc(com.netgrif.application.engine.importer.model.Arc importArc, Importer importer) throws IllegalArgumentException { + PTArc arc = ptArcFactory.get(importArc.getType()).get(); + arc.setSource(importer.getPlace(importArc.getSourceId())); + arc.setDestination(importer.getTransition(importArc.getDestinationId())); + return arc; + } + + private Multiplicity createMultiplicity(Expression multiplicity, Importer importer) { + String definition = multiplicity.getValue().trim(); + if (!multiplicity.isDynamic()) { + return new Multiplicity(Integer.parseInt(definition)); + } + Process process = importer.getProcess(); + if (process.getPlace(definition) != null) { + return new Multiplicity(definition, ReferenceType.PLACE); + } else if (process.getField(definition).isPresent()) { + return new Multiplicity(definition, ReferenceType.DATA_VARIABLE); + } else { + return new Multiplicity(definition); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/importer/service/ComponentFactory.java b/src/main/java/com/netgrif/application/engine/importer/service/ComponentFactory.java deleted file mode 100644 index e5851485571..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/ComponentFactory.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.netgrif.application.engine.importer.service; - - -import com.netgrif.application.engine.importer.model.Data; -import com.netgrif.application.engine.importer.model.DataType; -import com.netgrif.application.engine.importer.model.Option; -import com.netgrif.application.engine.importer.model.Property; -import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; -import com.netgrif.application.engine.petrinet.domain.Component; -import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.petrinet.domain.Icon; -import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationField; -import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField; -import com.netgrif.application.engine.petrinet.domain.dataset.Field; - -import java.util.*; -import java.util.stream.Collectors; - -@org.springframework.stereotype.Component -public class ComponentFactory { - - public static Map buildPropertyMap(List propertyList) { - Map properties = new HashMap<>(); - if (propertyList != null) { - propertyList.forEach(property -> { - properties.put(property.getKey(), property.getValue()); - }); - } - return properties; - } - - public static List buildIconsListWithValues(List iconList, Set values, String fieldId) throws MissingIconKeyException { - List icons = new ArrayList<>(); - for (com.netgrif.application.engine.importer.model.Icon icon : iconList) { - if (icon.getKey() != null && values.stream().map(I18nString::getDefaultValue).anyMatch(str -> str.equals(icon.getKey()))) { - if (icon.getType() == null) { - icons.add(new Icon(icon.getKey(), icon.getValue())); - } else { - icons.add(new Icon(icon.getKey(), icon.getValue(), icon.getType().value())); - } - } else { - throw new MissingIconKeyException(fieldId); - } - } - return icons; - } - - public static List buildIconsListWithOptions(List iconList, Map options, String fieldId) throws MissingIconKeyException { - List icons = new ArrayList<>(); - for (com.netgrif.application.engine.importer.model.Icon icon : iconList) { - if (icon.getKey() != null && options.containsKey(icon.getKey())) { - if (icon.getType() == null) { - icons.add(new Icon(icon.getKey(), icon.getValue())); - } else { - icons.add(new Icon(icon.getKey(), icon.getValue(), icon.getType().value())); - } - } else { - throw new MissingIconKeyException(fieldId); - } - } - return icons; - } - - public Component buildComponent(com.netgrif.application.engine.importer.model.Component importComponent, Importer importer, Data data) throws MissingIconKeyException { - if (importComponent.getProperties() != null && importComponent.getProperties().getOptionIcons() != null) { - return resolveComponent(importComponent, importer, data, null); - } - return buildComponent(importComponent); - } - - public Component buildComponent(com.netgrif.application.engine.importer.model.Component importComponent, Importer importer, Field field) throws MissingIconKeyException { - if (importComponent.getProperties() != null && importComponent.getProperties().getOptionIcons() != null) { - return resolveComponent(importComponent, importer, null, field); - } - return buildComponent(importComponent); - } - - public Component buildComponent(com.netgrif.application.engine.importer.model.Component importComponent) { - if (importComponent.getProperties() == null) { - return new Component(importComponent.getName(), buildPropertyMap(importComponent.getProperty())); - } - return new Component(importComponent.getName(), buildPropertyMap(importComponent.getProperties().getProperty())); - } - - private Component resolveComponent(com.netgrif.application.engine.importer.model.Component importComponent, Importer importer, Data data, Field field) throws MissingIconKeyException { - if (data != null) { - if ((data.getType() == DataType.ENUMERATION || data.getType() == DataType.MULTICHOICE) && data.getValues() != null && !data.getValues().isEmpty()) { - return new Component(importComponent.getName(), buildPropertyMap(importComponent.getProperties().getProperty()), - buildIconsListWithValues(importComponent.getProperties().getOptionIcons().getIcon(), data.getValues().stream().map(importer::toI18NString).collect(Collectors.toSet()), data.getId())); - } else if (data.getOptions() != null && !data.getOptions().getOption().isEmpty()) { - return new Component(importComponent.getName(), buildPropertyMap(importComponent.getProperties().getProperty()), - buildIconsListWithOptions(importComponent.getProperties().getOptionIcons().getIcon(), data.getOptions().getOption().stream() - .collect(Collectors.toMap(Option::getKey, importer::toI18NString, (o1, o2) -> o1, LinkedHashMap::new)), data.getId())); - } - } - if (field instanceof EnumerationField) { - return new Component(importComponent.getName(), buildPropertyMap(importComponent.getProperties().getProperty()), - buildIconsListWithValues(importComponent.getProperties().getOptionIcons().getIcon(), ((EnumerationField) field).getChoices(), field.getImportId())); - } - return new Component(importComponent.getName(), buildPropertyMap(importComponent.getProperties().getProperty()), - buildIconsListWithOptions(importComponent.getProperties().getOptionIcons().getIcon(), ((EnumerationMapField) field).getOptions(), field.getImportId())); - } -} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/FieldFactory.java b/src/main/java/com/netgrif/application/engine/importer/service/FieldFactory.java index bbb0903f021..6cd7efa27ec 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/FieldFactory.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/FieldFactory.java @@ -1,16 +1,16 @@ package com.netgrif.application.engine.importer.service; import com.netgrif.application.engine.configuration.properties.DatabaseProperties; +import com.netgrif.application.engine.importer.model.Argument; import com.netgrif.application.engine.importer.model.Data; import com.netgrif.application.engine.importer.model.DataType; -import com.netgrif.application.engine.importer.model.Valid; import com.netgrif.application.engine.importer.service.builder.FieldBuilder; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; -import com.netgrif.application.engine.importer.service.validation.IDataValidator; import com.netgrif.application.engine.petrinet.domain.Component; -import com.netgrif.application.engine.petrinet.domain.I18nString; +import com.netgrif.application.engine.petrinet.domain.dataset.Arguments; import com.netgrif.application.engine.petrinet.domain.dataset.Field; import com.netgrif.application.engine.petrinet.domain.dataset.Validation; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -23,15 +23,11 @@ public final class FieldFactory { private final DatabaseProperties properties; - private final ComponentFactory componentFactory; - private final IDataValidator dataValidator; private final Map> builders; - public FieldFactory(DatabaseProperties properties, List> builders, ComponentFactory componentFactory, IDataValidator dataValidator) { + public FieldFactory(DatabaseProperties properties, List> builders) { this.properties = properties; this.builders = builders.stream().collect(Collectors.toMap(FieldBuilder::getType, Function.identity())); - this.componentFactory = componentFactory; - this.dataValidator = dataValidator; } Field getField(Data data, Importer importer) throws IllegalArgumentException, MissingIconKeyException { @@ -40,69 +36,54 @@ Field getField(Data data, Importer importer) throws IllegalArgumentException, throw new IllegalArgumentException("Field " + data.getId() + " has unsupported type " + data.getType()); } Field field = builder.build(data, importer); - field.setName(importer.toI18NString(data.getTitle())); field.setImportId(data.getId()); + field.setTitle(importer.toI18NString(data.getTitle())); if (data.isImmediate() != null) { field.setImmediate(data.isImmediate()); } - if (data.getLength() != null) { - field.setLength(data.getLength()); - } - if (data.getDesc() != null) + if (data.getDesc() != null) { field.setDescription(importer.toI18NString(data.getDesc())); - - if (data.getPlaceholder() != null) + } + if (data.getPlaceholder() != null) { field.setPlaceholder(importer.toI18NString(data.getPlaceholder())); - - // TODO: release/8.0.0 validation register - // TODO: release/8.0.0 valid deprecated - if (data.getValid() != null) { - List list = data.getValid(); - for (Valid item : list) { - // TODO: release/8.0.0 new I18nString? - field.addValidation(new Validation(item.getValue(), new I18nString())); - } } if (data.getValidations() != null) { - List list = data.getValidations().getValidation(); - for (com.netgrif.application.engine.importer.model.Validation item : list) { - field.addValidation(new Validation(item.getExpression().getValue(), importer.toI18NString(item.getMessage()))); - } + createValidation(data, importer, field); } if (data.getComponent() != null) { - Component component = componentFactory.buildComponent(data.getComponent(), importer, data); + Component component = importer.createComponent(data.getComponent()); field.setComponent(component); } - if (data.getView() != null) { - log.warn("Data attribute [view] in field [{}] is deprecated.", field.getImportId()); - } - if (data.getFormat() != null) { - log.warn("Data attribute [format] in field [{}] is deprecated.", field.getImportId()); - } - setEncryption(field, data); - - dataValidator.checkDeprecatedAttributes(data); +// dataValidator.checkDeprecatedAttributes(data); return field; } -//TODO: release/8.0.0 merge check - /*private void resolveComponent(Field field, Case useCase, String transitionId) { - if (useCase.getDataField(field.getStringId()).hasComponent(transitionId)) { - field.setComponent(useCase.getDataField(field.getStringId()).getDataRefComponents().get(transitionId)); - } else if (useCase.getDataField(field.getStringId()).hasComponent()) { - field.setComponent(useCase.getDataField(field.getStringId()).getComponent()); + private void createValidation(Data data, Importer importer, Field field) { + for (com.netgrif.application.engine.importer.model.Validation item : data.getValidations().getValidation()) { + Arguments clientArguments = new Arguments(); + if (item.getClientArguments() != null) { + this.createArguments(item.getServerArguments().getArgument(), clientArguments); + } + Arguments serverArguments = new Arguments(); + if (item.getServerArguments() != null) { + this.createArguments(item.getServerArguments().getArgument(), serverArguments); + } + field.addValidation(new Validation(item.getName(), clientArguments, serverArguments, importer.toI18NString(item.getMessage()))); } - }*/ - /* private StringCollectionField buildStringCollectionField(Data data, Importer importer) { - StringCollectionField field = new StringCollectionField(); - setDefaultValues(field, data, defaultValues -> { - if (defaultValues != null) { - field.setDefaultValue(defaultValues); + } + + private void createArguments(List importedArguments, Arguments arguments) { + for (Argument importedArgument : importedArguments) { + Expression argument; + if (importedArgument.isDynamic() != null && importedArgument.isDynamic()) { + argument = Expression.ofDynamic(importedArgument.getValue()); + } else { + argument = Expression.ofStatic(importedArgument.getValue()); } - }); - return field; - }*/ + arguments.addArgument(argument); + } + } private void setEncryption(Field field, Data data) { if (data.getEncryption() != null && data.getEncryption().isValue()) { diff --git a/src/main/java/com/netgrif/application/engine/importer/service/FunctionFactory.java b/src/main/java/com/netgrif/application/engine/importer/service/FunctionFactory.java deleted file mode 100644 index 3ce6cc95715..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/FunctionFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.netgrif.application.engine.importer.service; - -import com.netgrif.application.engine.petrinet.domain.Function; -import com.netgrif.application.engine.petrinet.domain.FunctionScope; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -public final class FunctionFactory { - - public Function getFunction(com.netgrif.application.engine.importer.model.Function function) { - Function function1 = new Function(); - - function1.setDefinition(function.getValue()); - function1.setName(function.getName()); - function1.setScope(FunctionScope.valueOf(function.getScope().name())); - - return function1; - } -} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/ImportResult.java b/src/main/java/com/netgrif/application/engine/importer/service/ImportResult.java new file mode 100644 index 00000000000..cd8ab1474dc --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/ImportResult.java @@ -0,0 +1,21 @@ +package com.netgrif.application.engine.importer.service; + +import com.netgrif.application.engine.authorization.domain.ProcessRole; +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.utils.UniqueKeyMapWrapper; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class ImportResult { + + private Process process; // todo: release/8.0.0 process as optional? + private UniqueKeyMapWrapper roles = new UniqueKeyMapWrapper<>(); + // TODO: release/8.0.0 info, warn, error messages - definovat message a ich preklady + + public void addRole(ProcessRole processRole) { + this.roles.put(processRole.getImportId(), processRole); + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/Importer.java b/src/main/java/com/netgrif/application/engine/importer/service/Importer.java index 3edff43175f..8e8113a122c 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/Importer.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/Importer.java @@ -1,53 +1,53 @@ package com.netgrif.application.engine.importer.service; +import com.netgrif.application.engine.authorization.domain.ProcessRole; +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.configuration.LayoutFlexConfiguration; +import com.netgrif.application.engine.configuration.LayoutGridConfiguration; import com.netgrif.application.engine.importer.model.*; import com.netgrif.application.engine.importer.model.DataRef; +import com.netgrif.application.engine.importer.service.evaluation.IActionEvaluator; +import com.netgrif.application.engine.importer.service.evaluation.IFunctionEvaluator; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; -import com.netgrif.application.engine.importer.service.validation.IActionValidator; -import com.netgrif.application.engine.importer.service.validation.IDocumentValidator; -import com.netgrif.application.engine.importer.service.validation.ILogicValidator; -import com.netgrif.application.engine.importer.service.validation.ITransitionValidator; +import com.netgrif.application.engine.importer.service.trigger.TriggerFactory; +import com.netgrif.application.engine.importer.service.validation.IProcessValidator; import com.netgrif.application.engine.petrinet.domain.Component; -import com.netgrif.application.engine.petrinet.domain.DataGroup; +import com.netgrif.application.engine.petrinet.domain.Function; import com.netgrif.application.engine.petrinet.domain.Place; -import com.netgrif.application.engine.petrinet.domain.Transaction; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.Transition; import com.netgrif.application.engine.petrinet.domain.*; -import com.netgrif.application.engine.petrinet.domain.arcs.Arc; -import com.netgrif.application.engine.petrinet.domain.arcs.reference.Reference; -import com.netgrif.application.engine.petrinet.domain.arcs.reference.Type; import com.netgrif.application.engine.petrinet.domain.dataset.Field; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; import com.netgrif.application.engine.petrinet.domain.dataset.logic.FieldBehavior; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.FieldLayout; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionRunner; +import com.netgrif.application.engine.petrinet.domain.events.CaseEvent; import com.netgrif.application.engine.petrinet.domain.events.DataEvent; -import com.netgrif.application.engine.petrinet.domain.layout.DataGroupLayout; -import com.netgrif.application.engine.petrinet.domain.layout.TaskLayout; -import com.netgrif.application.engine.petrinet.domain.policies.AssignPolicy; -import com.netgrif.application.engine.petrinet.domain.policies.DataFocusPolicy; -import com.netgrif.application.engine.petrinet.domain.policies.FinishPolicy; -import com.netgrif.application.engine.petrinet.domain.roles.AssignedUserPermission; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; +import com.netgrif.application.engine.petrinet.domain.events.Event; +import com.netgrif.application.engine.petrinet.domain.events.ProcessEvent; +import com.netgrif.application.engine.petrinet.domain.events.RoleEvent; +import com.netgrif.application.engine.petrinet.domain.layout.LayoutContainer; +import com.netgrif.application.engine.petrinet.domain.layout.LayoutItem; +import com.netgrif.application.engine.petrinet.domain.layout.LayoutObjectType; import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; -import com.netgrif.application.engine.petrinet.service.ArcFactory; +import com.netgrif.application.engine.petrinet.domain.version.Version; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; +import com.netgrif.application.engine.utils.UniqueKeyMapWrapper; import com.netgrif.application.engine.workflow.domain.DataFieldBehavior; -import com.netgrif.application.engine.workflow.domain.FileStorageConfiguration; -import com.netgrif.application.engine.workflow.domain.triggers.Trigger; -import com.netgrif.application.engine.workflow.service.interfaces.IFieldActionsCacheService; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.BooleanUtils; import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; -import java.io.*; -import java.nio.file.Path; +import javax.xml.bind.annotation.XmlElement; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @@ -56,28 +56,20 @@ public class Importer { public static final String FILE_EXTENSION = ".xml"; - public static final String FIELD_KEYWORD = "f"; - public static final String TRANSITION_KEYWORD = "t"; - - public static final String DEFAULT_FIELD_TEMPLATE = "material"; - public static final String DEFAULT_FIELD_APPEARANCE = "outline"; - public static final String DEFAULT_FIELD_ALIGNMENT = null; - @Getter - protected Document document; - protected PetriNet net; - protected ProcessRole defaultRole; - protected ProcessRole anonymousRole; + protected com.netgrif.application.engine.importer.model.Process importedProcess; @Getter - protected Map roles; - protected Map> fields; - protected Map transitions; - protected Map places; - protected Map transactions; + protected Process process; + @Getter + protected ImportResult result; + protected Role defaultProcessRole; + protected Role anonymousProcessRole; + protected boolean isDefaultRoleEnabled = false; + protected boolean isAnonymousRoleEnabled = false; + protected Map i18n; - protected Map actions; - protected Map actionRefs; - protected List functions; + protected List missingMetaData; + protected List actions; @Autowired protected AllDataConfiguration allDataConfiguration; @@ -85,1246 +77,784 @@ public class Importer { @Autowired protected FieldFactory fieldFactory; - @Autowired - protected FunctionFactory functionFactory; - @Autowired protected IPetriNetService service; @Autowired - protected IProcessRoleService processRoleService; + protected IRoleService roleService; @Autowired - protected ArcFactory arcFactory; + protected IPetriNetService petriNetService; @Autowired - protected RoleFactory roleFactory; + protected ArcImporter arcImporter; @Autowired - protected TriggerFactory triggerFactory; + protected PermissionFactory permissionFactory; @Autowired - protected IActionValidator actionValidator; - - @Autowired - protected ActionRunner actionsRunner; + protected TriggerFactory triggerFactory; @Autowired - protected FileStorageConfiguration fileStorageConfiguration; + protected IActionEvaluator actionEvaluator; @Autowired - protected ComponentFactory componentFactory; + protected IFunctionEvaluator functionEvaluator; @Autowired - protected IFieldActionsCacheService actionsCacheService; + protected IProcessValidator processValidator; @Autowired - private IDocumentValidator documentValidator; + private LayoutFlexConfiguration flexConfiguration; @Autowired - private ITransitionValidator transitionValidator; + private LayoutGridConfiguration gridConfiguration; - @Autowired - private ILogicValidator logicValidator; + public Importer() { + this.i18n = new HashMap<>(); + this.missingMetaData = new ArrayList<>(); + this.actions = new LinkedList<>(); + this.result = new ImportResult(); + } - public Optional importPetriNet(InputStream xml) throws MissingPetriNetMetaDataException, MissingIconKeyException { + public ImportResult importPetriNet(InputStream xml) throws MissingPetriNetMetaDataException, MissingIconKeyException { try { initialize(); unmarshallXml(xml); - return createPetriNet(); + return createProcess(); } catch (JAXBException e) { log.error("Importing Petri net failed: ", e); } - return Optional.empty(); - } - - public Optional importPetriNet(File xml) throws MissingPetriNetMetaDataException, MissingIconKeyException { - try { - return importPetriNet(new FileInputStream(xml)); - } catch (FileNotFoundException e) { - log.error("Importing Petri net failed: ", e); - } - return Optional.empty(); + return new ImportResult(); } protected void initialize() { - this.roles = new HashMap<>(); - this.transitions = new HashMap<>(); - this.places = new HashMap<>(); - this.fields = new HashMap<>(); - this.transactions = new HashMap<>(); - this.defaultRole = processRoleService.defaultRole(); - this.anonymousRole = processRoleService.anonymousRole(); - this.i18n = new HashMap<>(); - this.actions = new HashMap<>(); - this.actionRefs = new HashMap<>(); - this.functions = new LinkedList<>(); + this.defaultProcessRole = roleService.findDefaultRole(); + this.anonymousProcessRole = roleService.findAnonymousRole(); } - public Document unmarshallXml(InputStream xml) throws JAXBException { - JAXBContext jaxbContext = JAXBContext.newInstance(Document.class); - + public com.netgrif.application.engine.importer.model.Process unmarshallXml(InputStream xml) throws JAXBException { + JAXBContext jaxbContext = JAXBContext.newInstance(com.netgrif.application.engine.importer.model.Process.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - document = (Document) jaxbUnmarshaller.unmarshal(xml); - return document; - } - - public Path saveNetFile(PetriNet net, InputStream xmlFile) throws IOException { - File savedFile = new File(fileStorageConfiguration.getStorageArchived() + net.getStringId() + "-" + net.getTitle() + FILE_EXTENSION); - savedFile.getParentFile().mkdirs(); // TODO: release/8.0.0 return false? storage should be created so maybe delete this line? - net.setImportXmlPath(savedFile.getPath()); - copyInputStreamToFile(xmlFile, savedFile); - return savedFile.toPath(); + importedProcess = (com.netgrif.application.engine.importer.model.Process) jaxbUnmarshaller.unmarshal(xml); + return importedProcess; } - protected Optional createPetriNet() throws MissingPetriNetMetaDataException, MissingIconKeyException { - net = new PetriNet(); + protected ImportResult createProcess() throws MissingPetriNetMetaDataException, MissingIconKeyException { + initializeProcess(); - documentValidator.checkConflictingAttributes(document, document.getUsersRef(), document.getUserRef(), "usersRef", "userRef"); - documentValidator.checkDeprecatedAttributes(document); - document.getI18N().forEach(this::addI18N); + importedProcess.getI18N().forEach(this::addI18N); setMetaData(); addAllDataTransition(); - net.setIcon(document.getIcon()); - net.setDefaultRoleEnabled(document.isDefaultRole() != null && document.isDefaultRole()); - net.setAnonymousRoleEnabled(document.isAnonymousRole() != null && document.isAnonymousRole()); - - document.getRole().forEach(this::createRole); - document.getData().forEach(this::createDataSet); - document.getTransaction().forEach(this::createTransaction); - document.getPlace().forEach(this::createPlace); - document.getTransition().forEach(this::createTransition); - document.getArc().forEach(this::createArc); - document.getMapping().forEach(this::applyMapping); - document.getData().forEach(this::resolveDataActions); - document.getTransition().forEach(this::resolveTransitionActions); - document.getData().forEach(this::addActionRefs); - actionRefs.forEach(this::resolveActionRefs); - document.getFunction().forEach(this::createFunction); - document.getRoleRef().forEach(this::resolveRoleRef); - document.getUsersRef().forEach(this::resolveUserRef); - document.getUserRef().forEach(this::resolveUserRef); + importedProcess.getRole().forEach(this::createRole); + importedProcess.getData().forEach(this::createDataSet); + importedProcess.getPlace().forEach(this::createPlace); + importedProcess.getTransition().forEach(this::createTransition); + importedProcess.getArc().forEach(this::createArc); + importedProcess.getFunction().forEach(this::createFunction); + importedProcess.getRoleRef().forEach(this::createProcessPermissions); addPredefinedRolesWithDefaultPermissions(); - resolveProcessEvents(document.getProcessEvents()); - resolveCaseEvents(document.getCaseEvents()); - evaluateFunctions(); - actions.forEach(this::evaluateActions); - - if (document.getCaseName() != null && document.getCaseName().isDynamic()) { - net.setDefaultCaseNameExpression(new Expression(document.getCaseName().getValue(), document.getCaseName().isDynamic())); - } else { - net.setDefaultCaseName(toI18NString(document.getCaseName())); + if (importedProcess.getProcessEvents() != null) { + importedProcess.getProcessEvents().getEvent().forEach(this::createProcessEvent); } - if (document.getTags() != null) { - net.setTags(this.buildTagsMap(document.getTags().getTag())); + if (importedProcess.getCaseEvents() != null) { + importedProcess.getCaseEvents().getEvent().forEach(this::createCaseEvent); } - return Optional.of(net); - } - - protected void addAllDataTransition() { - com.netgrif.application.engine.importer.model.Transition allDataConfig = allDataConfiguration.getAllData(); - if (document.getTransition().stream().anyMatch(transition -> allDataConfig.getId().equals(transition.getId()))) { - return; - } - com.netgrif.application.engine.importer.model.DataGroup configDataGroup = allDataConfig.getDataGroup().get(0); - int y = 0; - com.netgrif.application.engine.importer.model.Transition allDataTransition = new com.netgrif.application.engine.importer.model.Transition(); - allDataTransition.setId(allDataConfig.getId()); - allDataTransition.setX(allDataConfig.getX()); - allDataTransition.setY(allDataConfig.getY()); - allDataTransition.setLabel(allDataConfig.getLabel()); - allDataTransition.setIcon(allDataConfig.getIcon()); - allDataTransition.setPriority(allDataConfig.getPriority()); - allDataTransition.setAssignPolicy(allDataConfig.getAssignPolicy()); - allDataTransition.setFinishPolicy(allDataConfig.getFinishPolicy()); - // TODO: NAE-1858: all properties - com.netgrif.application.engine.importer.model.DataGroup allDataGroup = new com.netgrif.application.engine.importer.model.DataGroup(); - for (Data field : document.getData()) { - DataRef dataRef = new DataRef(); - dataRef.setId(field.getId()); - Layout layout = new Layout(); - layout.setCols(configDataGroup.getCols()); - layout.setRows(1); - layout.setX(0); - layout.setY(y); - layout.setOffset(0); - layout.setTemplate(Template.MATERIAL); - layout.setAppearance(Appearance.OUTLINE); - dataRef.setLayout(layout); - Logic logic = new Logic(); - logic.getBehavior().add(Behavior.EDITABLE); - dataRef.setLogic(logic); - allDataGroup.getDataRef().add(dataRef); - y++; - } - allDataTransition.getDataGroup().add(allDataGroup); - document.getTransition().add(allDataTransition); - } - - protected void resolveRoleRef(CaseRoleRef roleRef) { - CaseLogic logic = roleRef.getCaseLogic(); - String roleId = getRole(roleRef.getId()).getStringId(); - - if (logic == null || roleId == null) { - return; - } - if (logic.isView() != null && !logic.isView()) { - net.addNegativeViewRole(roleId); - } - - net.addPermission(roleId, roleFactory.getProcessPermissions(logic)); - } - - protected void createFunction(com.netgrif.application.engine.importer.model.Function function) { - com.netgrif.application.engine.petrinet.domain.Function fun = functionFactory.getFunction(function); + functionEvaluator.evaluate(process.getFunctions()); + actionEvaluator.evaluate(actions, process.getFunctions()); + processValidator.validate(process); - net.addFunction(fun); - functions.add(fun); + return this.result; } - protected void resolveUserRef(CaseUserRef userRef) { - CaseLogic logic = userRef.getCaseLogic(); - String usersId = userRef.getId(); - - if (logic == null || usersId == null) { - return; - } - - net.addUserPermission(usersId, roleFactory.getProcessPermissions(logic)); - } - - protected void resolveProcessEvents(ProcessEvents processEvents) { - if (processEvents != null && processEvents.getEvent() != null) { - net.setProcessEvents(createProcessEventsMap(processEvents.getEvent())); - } - } - - protected void resolveCaseEvents(CaseEvents caseEvents) { - if (caseEvents != null && caseEvents.getEvent() != null) { - net.setCaseEvents(createCaseEventsMap(caseEvents.getEvent())); + protected void initializeProcess() throws IllegalArgumentException { + Extension extension = importedProcess.getExtends(); + if (extension != null) { + initializeWithChildProcess(extension); + } else { + process = new Process(); } + result.setProcess(process); } - protected void evaluateFunctions() { - try { - actionsCacheService.evaluateFunctions(functions); - } catch (Exception e) { - throw new IllegalArgumentException("Could not evaluate functions: " + e.getMessage(), e); + protected void initializeWithChildProcess(Extension extension) { + if (areExtensionAttributesEmpty(extension)) { + throw new IllegalArgumentException("Parent identifier or version is empty."); } - } - - protected void evaluateActions(String s, Action action) { - try { - actionsRunner.getActionCode(action, functions, true); - } catch (Exception e) { - throw new IllegalArgumentException("Could not evaluate action[" + action.getImportId() + "]: \n " + action.getDefinition(), e); + Process parentNet = petriNetService.getPetriNet(extension.getId(), Version.of(extension.getVersion())); + if (parentNet == null) { + throw new IllegalArgumentException("Parent petri net not found."); } + process = parentNet.clone(); + process.setCreationDate(LocalDateTime.now()); + // transition must be removed since it's going to be added later with proper data + process.getTransitions().remove(allDataConfiguration.getAllData().getId()); + process.setObjectId(new ObjectId()); + process.addParentIdentifier(new PetriNetIdentifier( + parentNet.getIdentifier(), + parentNet.getVersion(), + parentNet.getObjectId() + )); } - protected void resolveActionRefs(String actionId, Action action) { - Action referenced = actions.get(actionId); - if (referenced == null) { - throw new IllegalArgumentException("Invalid action reference with id [" + actionId + "]"); - } - action.setDefinition(referenced.getDefinition()); - action.setTrigger(referenced.getTrigger()); + protected static boolean areExtensionAttributesEmpty(Extension extension) { + return extension.getId() == null || extension.getId().isBlank() + || extension.getVersion() == null || extension.getVersion().isBlank(); } - protected void addI18N(I18N importI18N) { + protected void addI18N(com.netgrif.application.engine.importer.model.I18N importI18N) { String locale = importI18N.getLocale(); importI18N.getI18NString().forEach(translation -> addTranslation(translation, locale)); } - protected void addTranslation(I18NStringType i18NStringType, String locale) { - String name = i18NStringType.getName(); - I18nString translation = getI18n(name); - if (translation == null) { - translation = new I18nString(); - i18n.put(name, translation); - } + protected void addTranslation(com.netgrif.application.engine.importer.model.I18NStringType i18NStringType, String locale) { + String id = i18NStringType.getId(); + I18nString translation = i18n.computeIfAbsent(id, k -> new I18nString()); translation.addTranslation(locale, i18NStringType.getValue()); } - protected void applyMapping(Mapping mapping) throws MissingIconKeyException { - Transition transition = getTransition(mapping.getTransitionRef()); - mapping.getRoleRef().forEach(roleRef -> addRoleLogic(transition, roleRef)); - mapping.getDataRef().forEach(dataRef -> addDataLogic(transition, dataRef)); - for (com.netgrif.application.engine.importer.model.DataGroup dataGroup : mapping.getDataGroup()) { - addDataGroup(transition, dataGroup, mapping.getDataGroup().indexOf(dataGroup)); + public I18nString toI18NString(com.netgrif.application.engine.importer.model.I18NStringType imported) { + if (imported == null) { + return new I18nString(""); + } + String key = imported.getValue(); + if (imported.getId() != null) { + key = imported.getId(); + } + if (imported instanceof com.netgrif.application.engine.importer.model.Option) { + key = ((com.netgrif.application.engine.importer.model.Option) imported).getKey(); + } + I18nString string = i18n.getOrDefault(imported.getId(), new I18nString(key, imported.getValue())); + if (string.getDefaultValue() == null) { + string.setDefaultValue(imported.getValue()); } - mapping.getTrigger().forEach(trigger -> addTrigger(transition, trigger)); + return string; } - protected void resolveDataActions(Data data) { - String fieldId = data.getId(); - if (data.getEvent() != null && !data.getEvent().isEmpty()) { - getField(fieldId).setEvents(buildEvents(fieldId, data.getEvent(), null)); + protected void setMetaData() throws MissingPetriNetMetaDataException { + checkMetaData(importedProcess.getId(), () -> { + process.setImportId(importedProcess.getId()); + process.setIdentifier(importedProcess.getId()); + }, ""); + checkMetaData(importedProcess.getVersion(), () -> process.setVersion(Version.of(importedProcess.getVersion())), + ""); + checkMetaData(importedProcess.getTitle(), () -> process.setTitle(toI18NString(importedProcess.getTitle())), + ""); + // TODO: release/8.0.0 extension from NAE-1973 + process.setIcon(importedProcess.getIcon()); + + if (importedProcess.getCaseName() != null) { + I18nExpression caseName = new I18nExpression(importedProcess.getCaseName().getValue()); + caseName.setDynamic(importedProcess.getCaseName().isDynamic()); + caseName.setKey(importedProcess.getCaseName().getId()); + if (i18n.containsKey(caseName.getKey())) { + caseName.setTranslations(i18n.get(caseName.getKey()).getTranslations()); + } + process.setDefaultCaseName(caseName); } - if (data.getAction() != null) { - Map<DataEventType, DataEvent> events = getField(fieldId).getEvents(); + createProperties(importedProcess.getProperties(), process.getProperties()); - List<com.netgrif.application.engine.importer.model.Action> filteredActions = filterActionsByTrigger(data.getAction(), DataEventType.GET); - addActionsToEvent(buildActions(filteredActions, fieldId, null), DataEventType.GET, events); + // TODO: release/8.0.0 rework + this.isDefaultRoleEnabled = (importedProcess.isDefaultRole() != null && importedProcess.isDefaultRole()); + this.isAnonymousRoleEnabled = (importedProcess.isAnonymousRole() != null && importedProcess.isAnonymousRole()); - filteredActions = filterActionsByTrigger(data.getAction(), DataEventType.SET); - addActionsToEvent(buildActions(filteredActions, fieldId, null), DataEventType.SET, events); + if (!missingMetaData.isEmpty()) { + throw new MissingPetriNetMetaDataException(missingMetaData); } } - private List<com.netgrif.application.engine.importer.model.Action> filterActionsByTrigger(List<com.netgrif.application.engine.importer.model.Action> actions, DataEventType trigger) { - return actions.stream() - .filter(action -> action.getTrigger().equalsIgnoreCase(trigger.toString())) - .collect(Collectors.toList()); - } - - private void addActionsToEvent(List<Action> actions, DataEventType type, Map<DataEventType, DataEvent> events) { - if (actions.isEmpty()) return; - if (events.get(type) != null) { - events.get(type).addToActionsByDefaultPhase(actions); - return; + protected void checkMetaData(Object metadata, Runnable onPresent, String metadataTag) { + if (metadata != null) { + onPresent.run(); + } else { + missingMetaData.add(metadataTag); } - events.computeIfAbsent(type, k -> { - DataEvent event = new DataEvent(); - event.setType(type); - event.addToActionsByDefaultPhase(actions); - event.setId(new ObjectId().toString()); - return event; - }); } - protected void addActionRefs(Data data) { - if (data.getActionRef() != null) { - List<Action> actions = buildActionRefs(data.getActionRef()); - getField(data.getId()).addActions(actions.stream().filter(action -> action.getTrigger() == DataEventType.GET).collect(Collectors.toList()), DataEventType.GET); - getField(data.getId()).addActions(actions.stream().filter(action -> action.getTrigger() == DataEventType.SET).collect(Collectors.toList()), DataEventType.SET); + protected void addAllDataTransition() { + // TODO: release/8.0.0 extend default Object process + com.netgrif.application.engine.importer.model.Transition allDataConfig = allDataConfiguration.getAllData(); + if (importedProcess.getTransition().stream().anyMatch(transition -> allDataConfig.getId().equals(transition.getId()))) { + return; } - } - - protected List<Action> buildActionRefs(List<ActionRef> actionRefs) { - return actionRefs.stream().map(ref -> actions.get(ref.getId())).collect(Collectors.toList()); - } + com.netgrif.application.engine.importer.model.Transition allDataTransition = new com.netgrif.application.engine.importer.model.Transition(); + // TODO: release/8.0.0 merge forms from NAE-1966 + allDataTransition.setId(allDataConfig.getId()); + allDataTransition.setX(allDataConfig.getX()); + allDataTransition.setY(allDataConfig.getY()); + allDataTransition.setTitle(allDataConfig.getTitle()); + allDataTransition.setIcon(allDataConfig.getIcon()); + allDataTransition.setAssignPolicy(allDataConfig.getAssignPolicy()); + allDataTransition.setFinishPolicy(allDataConfig.getFinishPolicy()); + // TODO: release/8.0.0 all properties + FlexContainer flex = new FlexContainer(); + for (com.netgrif.application.engine.importer.model.Data field : importedProcess.getData()) { + FlexItem flexItem = new FlexItem(); + com.netgrif.application.engine.importer.model.DataRef dataRef = new com.netgrif.application.engine.importer.model.DataRef(); - protected Action fromActionRef(ActionRef actionRef) { - Action placeholder = new Action(); - placeholder.setImportId(actionRef.getId()); - this.actionRefs.put(actionRef.getId(), placeholder); - return placeholder; - } + dataRef.setId(field.getId()); + com.netgrif.application.engine.importer.model.DataRefLogic logic = new com.netgrif.application.engine.importer.model.DataRefLogic(); + logic.setBehavior(com.netgrif.application.engine.importer.model.Behavior.EDITABLE); + dataRef.setLogic(logic); - protected void resolveTransitionActions(com.netgrif.application.engine.importer.model.Transition trans) { - if (trans.getDataRef() != null) { - resolveDataRefActions(trans.getDataRef(), trans); - } - if (trans.getDataGroup() != null) { - trans.getDataGroup().forEach(ref -> { - if (ref.getDataRef() != null) { - resolveDataRefActions(ref.getDataRef(), trans); - } - }); - } + flexItem.setDataRef(dataRef); + flex.getItem().add(flexItem); + } + allDataTransition.setFlex(flex); + importedProcess.getTransition().add(allDataTransition); + } + +// private void addActionsToEvent(List<Action> actions, com.netgrif.application.engine.importer.model.DataEventType type, Map<com.netgrif.application.engine.importer.model.DataEventType, DataEvent> events) { +// if (actions.isEmpty()) return; +// if (events.get(type) != null) { +// events.get(type).addToActionsByDefaultPhase(actions); +// return; +// } +// events.computeIfAbsent(type, k -> { +// DataEvent event = new DataEvent(); +// event.setType(type); +// event.addToActionsByDefaultPhase(actions); +// event.setId(new ObjectId().toString()); +// return event; +// }); +// } +// +// protected void resolveDataRefActions(List<DataRef> dataRef, com.netgrif.application.engine.importer.model.Transition trans) { +// dataRef.forEach(ref -> { +// String fieldId = getField(ref.getId()).getStringId(); +// Map<com.netgrif.application.engine.importer.model.DataEventType, DataEvent> dataEvents = new HashMap<>(); +// List<Action> getActions = new ArrayList<>(); +// List<Action> setActions = new ArrayList<>(); +// if (ref.getEvent() != null && !ref.getEvent().isEmpty()) { +// dataEvents = buildEvents(fieldId, ref.getEvent(), getTransition(trans.getId()).getStringId()); +// getTransition(trans.getId()).setDataEvents(fieldId, dataEvents); +// } +// if (ref.getLogic().getAction() != null) { +// getActions = buildActions(filterActionsByTrigger(ref.getLogic().getAction(), com.netgrif.application.engine.importer.model.DataEventType.GET), +// fieldId, getTransition(trans.getId()).getStringId()); +// setActions = buildActions(filterActionsByTrigger(ref.getLogic().getAction(), com.netgrif.application.engine.importer.model.DataEventType.SET), +// fieldId, getTransition(trans.getId()).getStringId()); +// } +// if (ref.getLogic().getActionRef() != null) { +// List<Action> fromActionRefs = buildActionRefs(ref.getLogic().getActionRef()); +// getActions.addAll(fromActionRefs.stream() +// .filter(action -> action.isTriggeredBy(com.netgrif.application.engine.importer.model.DataEventType.GET)).collect(Collectors.toList())); +// setActions.addAll(fromActionRefs.stream() +// .filter(action -> action.isTriggeredBy(com.netgrif.application.engine.importer.model.DataEventType.SET)).collect(Collectors.toList())); +// } +// +// addActionsToDataEvent(getActions, dataEvents, com.netgrif.application.engine.importer.model.DataEventType.GET); +// addActionsToDataEvent(setActions, dataEvents, com.netgrif.application.engine.importer.model.DataEventType.SET); +// getTransition(trans.getId()).setDataEvents(fieldId, dataEvents); +// }); +// } +// +// protected void addActionsToDataEvent(List<Action> actions, Map<com.netgrif.application.engine.importer.model.DataEventType, DataEvent> dataEvents, com.netgrif.application.engine.importer.model.DataEventType type) { +// if (!dataEvents.containsKey(type) || dataEvents.get(type).getId() == null) { +// dataEvents.put(type, createDefaultEvent(actions, type)); +// } else { +// dataEvents.get(type).addToActionsByDefaultPhase(actions); +// } +// } +// + protected void createArc(com.netgrif.application.engine.importer.model.Arc importArc) { + process.addArc(arcImporter.getArc(importArc, this)); } - protected void resolveDataRefActions(List<DataRef> dataRef, com.netgrif.application.engine.importer.model.Transition trans) { - dataRef.forEach(ref -> { - String fieldId = getField(ref.getId()).getStringId(); - Map<DataEventType, DataEvent> dataEvents = new HashMap<>(); - List<Action> getActions = new ArrayList<>(); - List<Action> setActions = new ArrayList<>(); - if (ref.getEvent() != null && !ref.getEvent().isEmpty()) { - dataEvents = buildEvents(fieldId, ref.getEvent(), getTransition(trans.getId()).getStringId()); - getTransition(trans.getId()).setDataEvents(fieldId, dataEvents); - } - if (ref.getLogic().getAction() != null) { - getActions = buildActions(filterActionsByTrigger(ref.getLogic().getAction(), DataEventType.GET), - fieldId, getTransition(trans.getId()).getStringId()); - setActions = buildActions(filterActionsByTrigger(ref.getLogic().getAction(), DataEventType.SET), - fieldId, getTransition(trans.getId()).getStringId()); - } - if (ref.getLogic().getActionRef() != null) { - List<Action> fromActionRefs = buildActionRefs(ref.getLogic().getActionRef()); - getActions.addAll(fromActionRefs.stream() - .filter(action -> action.isTriggeredBy(DataEventType.GET)).collect(Collectors.toList())); - setActions.addAll(fromActionRefs.stream() - .filter(action -> action.isTriggeredBy(DataEventType.SET)).collect(Collectors.toList())); - } - - addActionsToDataEvent(getActions, dataEvents, DataEventType.GET); - addActionsToDataEvent(setActions, dataEvents, DataEventType.SET); - getTransition(trans.getId()).setDataEvents(fieldId, dataEvents); - }); + protected boolean isInputArc(com.netgrif.application.engine.importer.model.Arc importArc) { + return this.process.getPlace(importArc.getSourceId()) != null; } - protected void addActionsToDataEvent(List<Action> actions, Map<DataEventType, DataEvent> dataEvents, DataEventType type) { - if (!dataEvents.containsKey(type) || dataEvents.get(type).getId() == null) { - dataEvents.put(type, createDefaultEvent(actions, type)); - } else { - dataEvents.get(type).addToActionsByDefaultPhase(actions); + protected Place getPlace(String id) { + Place place = process.getPlace(id); + if (place == null) { + throw new IllegalArgumentException(String.format("Place with id [%s] not found.", id)); } + return place; } - protected DataEvent createDefaultEvent(List<Action> actions, DataEventType type) { - DataEvent event = new DataEvent(); - event.setType(type); - event.setId(new ObjectId().toString()); - event.addToActionsByDefaultPhase(actions); - return event; - } - - protected void createArc(com.netgrif.application.engine.importer.model.Arc importArc) { - Arc arc = arcFactory.getArc(importArc); - arc.setImportId(importArc.getId()); - arc.setSource(getNode(importArc.getSourceId())); - arc.setDestination(getNode(importArc.getDestinationId())); - if (importArc.getReference() == null && arc.getReference() == null) { - arc.setMultiplicity(importArc.getMultiplicity()); - } - if (importArc.getReference() != null) { - if (!places.containsKey(importArc.getReference()) && !fields.containsKey(importArc.getReference())) { - throw new IllegalArgumentException("Place or Data variable with id [" + importArc.getReference() + "] referenced by Arc [" + importArc.getId() + "] could not be found."); - } - Reference reference = new Reference(); - reference.setReference(importArc.getReference()); - arc.setReference(reference); - } -// It has to be here for backwards compatibility of variable arcs - if (arc.getReference() != null) { - arc.getReference().setType((places.containsKey(arc.getReference().getReference())) ? Type.PLACE : Type.DATA); - } - if (importArc.getBreakpoint() != null) { - importArc.getBreakpoint().forEach(position -> arc.getBreakpoints().add(new Position(position.getX(), position.getY()))); + protected Transition getTransition(String id) { + Transition transition = process.getTransition(id); + if (transition == null) { + throw new IllegalArgumentException(String.format("Transition with id [%s] not found.", id)); } - - net.addArc(arc); + return transition; } - protected void createDataSet(Data importData) throws MissingIconKeyException { + protected void createDataSet(com.netgrif.application.engine.importer.model.Data importData) throws MissingIconKeyException { Field<?> field = fieldFactory.getField(importData, this); - - net.addDataSetField(field); - fields.put(importData.getId(), field); + if (importData.getEvent() != null) { + importData.getEvent().forEach(event -> field.addEvent(createDataEvent(event))); + } + createProperties(importData.getProperties(), field.getProperties()); + process.addDataSetField(field); } protected void createTransition(com.netgrif.application.engine.importer.model.Transition importTransition) throws MissingIconKeyException { - transitionValidator.checkConflictingAttributes(importTransition, importTransition.getUsersRef(), importTransition.getUserRef(), "usersRef", "userRef"); - transitionValidator.checkDeprecatedAttributes(importTransition); - Transition transition = new Transition(); transition.setImportId(importTransition.getId()); - transition.setTitle(importTransition.getLabel() != null ? toI18NString(importTransition.getLabel()) : new I18nString("")); - transition.setPosition(importTransition.getX(), importTransition.getY()); - if (importTransition.getTags() != null) { - transition.setTags(this.buildTagsMap(importTransition.getTags().getTag())); - } - - if (importTransition.getLayout() != null) { - transition.setLayout(new TaskLayout(importTransition)); - } - - transition.setPriority(importTransition.getPriority()); + transition.setTitle(toI18NString(importTransition.getTitle())); + createProperties(importTransition.getProperties(), transition.getProperties()); transition.setIcon(importTransition.getIcon()); transition.setAssignPolicy(toAssignPolicy(importTransition.getAssignPolicy())); - transition.setDataFocusPolicy(toDataFocusPolicy(importTransition.getDataFocusPolicy())); transition.setFinishPolicy(toFinishPolicy(importTransition.getFinishPolicy())); - if (importTransition.getRoleRef() != null) { - importTransition.getRoleRef().forEach(roleRef -> - addRoleLogic(transition, roleRef) - ); - } - /* @Deprecated - This 'importTransition.getUsersRef()' is deprecated, will be removed in future releases*/ - if (importTransition.getUsersRef() != null) { - importTransition.getUsersRef().forEach(usersRef -> - addUserLogic(transition, usersRef)); - } - - if (importTransition.getUserRef() != null) { - importTransition.getUserRef().forEach(userRef -> - addUserLogic(transition, userRef)); - } - - if (importTransition.getDataRef() != null) { - for (com.netgrif.application.engine.importer.model.DataRef dataRef : importTransition.getDataRef()) { - addDataWithDefaultGroup(transition, dataRef); - } + importTransition.getRoleRef().forEach(roleRef -> createTaskPermissions(transition, roleRef)); } if (importTransition.getTrigger() != null) { - importTransition.getTrigger().forEach(trigger -> - addTrigger(transition, trigger) - ); - } - if (importTransition.getTransactionRef() != null) { - addToTransaction(transition, importTransition.getTransactionRef()); - } - if (importTransition.getDataGroup() != null) { - for (com.netgrif.application.engine.importer.model.DataGroup dataGroup : importTransition.getDataGroup()) { - addDataGroup(transition, dataGroup, importTransition.getDataGroup().indexOf(dataGroup)); - } + importTransition.getTrigger().forEach(trigger -> createTrigger(transition, trigger)); } addPredefinedRolesWithDefaultPermissions(importTransition, transition); if (importTransition.getEvent() != null) { - importTransition.getEvent().forEach(event -> - transition.addEvent(addEvent(transition.getImportId(), event)) - ); - } - if (importTransition.getAssignedUser() != null) { - addAssignedUserPolicy(importTransition, transition); + importTransition.getEvent().forEach(event -> transition.addEvent(createEvent(event))); } + resolveLayoutContainer(importTransition, transition); - net.addTransition(transition); - transitions.put(importTransition.getId(), transition); + process.addTransition(transition); } - protected void addAssignedUserPolicy(com.netgrif.application.engine.importer.model.Transition importTransition, Transition transition) { - if (importTransition.getAssignedUser().isCancel() != null) { - transition.getAssignedUserPolicy().put(AssignedUserPermission.CANCEL, importTransition.getAssignedUser().isCancel()); - } - if (importTransition.getAssignedUser().isReassign() != null) { - transition.getAssignedUserPolicy().put(AssignedUserPermission.REASSIGN, importTransition.getAssignedUser().isReassign()); - } - } - - protected com.netgrif.application.engine.petrinet.domain.events.Event addEvent(String transitionId, com.netgrif.application.engine.importer.model.Event imported) { - com.netgrif.application.engine.petrinet.domain.events.Event event = new com.netgrif.application.engine.petrinet.domain.events.Event(); - event.setImportId(imported.getId()); - event.setMessage(toI18NString(imported.getMessage())); - event.setTitle(toI18NString(imported.getTitle())); - event.setType(EventType.valueOf(imported.getType().value().toUpperCase())); - event.setPostActions(parsePostActions(transitionId, imported)); - event.setPreActions(parsePreActions(transitionId, imported)); - + protected Event createEvent(com.netgrif.application.engine.importer.model.Event importedEvent) { + Event event = new Event(); + event.setTitle(toI18NString(importedEvent.getTitle())); + event.setType(com.netgrif.application.engine.importer.model.EventType.valueOf(importedEvent.getType().value().toUpperCase())); + this.addBaseEventProperties(event, importedEvent); return event; } - protected com.netgrif.application.engine.petrinet.domain.events.ProcessEvent addProcessEvent(com.netgrif.application.engine.importer.model.ProcessEvent imported) { - com.netgrif.application.engine.petrinet.domain.events.ProcessEvent event = new com.netgrif.application.engine.petrinet.domain.events.ProcessEvent(); - event.setMessage(toI18NString(imported.getMessage())); - event.setImportId(imported.getId()); - event.setType(ProcessEventType.valueOf(imported.getType().value().toUpperCase())); - event.setPostActions(parsePostActions(null, imported)); - event.setPreActions(parsePreActions(null, imported)); - + protected RoleEvent createEvent(com.netgrif.application.engine.importer.model.RoleEvent importedEvent) { + RoleEvent event = new RoleEvent(); + event.setTitle(toI18NString(importedEvent.getTitle())); + event.setType(com.netgrif.application.engine.importer.model.RoleEventType.valueOf(importedEvent.getType().value().toUpperCase())); + this.addBaseEventProperties(event, importedEvent); return event; } - - protected com.netgrif.application.engine.petrinet.domain.events.CaseEvent addCaseEvent(com.netgrif.application.engine.importer.model.CaseEvent imported) { - com.netgrif.application.engine.petrinet.domain.events.CaseEvent event = new com.netgrif.application.engine.petrinet.domain.events.CaseEvent(); - event.setMessage(toI18NString(imported.getMessage())); + protected void addBaseEventProperties(com.netgrif.application.engine.petrinet.domain.events.BaseEvent event, com.netgrif.application.engine.importer.model.BaseEvent imported) { event.setImportId(imported.getId()); - event.setType(CaseEventType.valueOf(imported.getType().value().toUpperCase())); - event.setPostActions(parsePostActions(null, imported)); - event.setPreActions(parsePreActions(null, imported)); - - return event; - } - - protected List<Action> parsePostActions(String transitionId, com.netgrif.application.engine.importer.model.BaseEvent imported) { - return parsePhaseActions(EventPhaseType.POST, transitionId, imported); - } - - protected List<Action> parsePreActions(String transitionId, com.netgrif.application.engine.importer.model.BaseEvent imported) { - return parsePhaseActions(EventPhaseType.PRE, transitionId, imported); - } - - protected List<Action> parsePhaseActions(EventPhaseType phase, String transitionId, com.netgrif.application.engine.importer.model.BaseEvent imported) { - List<Action> actionList = imported.getActions().stream() - .filter(actions -> actions.getPhase().equals(phase)) - .flatMap(actions -> actions.getAction().parallelStream() - .map(action -> parseAction(transitionId, action))) - .collect(Collectors.toList()); - actionList.addAll(imported.getActions().stream() - .filter(actions -> actions.getPhase().equals(phase)) - .flatMap(actions -> actions.getActionRef().stream().map(this::fromActionRef)) - .collect(Collectors.toList())); - return actionList; + event.setMessage(toI18NString(imported.getMessage())); + event.setPreActions(parsePhaseActions(com.netgrif.application.engine.importer.model.EventPhaseType.PRE, imported)); + event.setPostActions(parsePhaseActions(com.netgrif.application.engine.importer.model.EventPhaseType.POST, imported)); } - protected List<Action> parsePhaseActions(String fieldId, EventPhaseType phase, DataEventType trigger, String transitionId, com.netgrif.application.engine.importer.model.DataEvent dataEvent) { - List<Action> actionList = dataEvent.getActions().stream() + protected List<Action> parsePhaseActions(com.netgrif.application.engine.importer.model.EventPhaseType phase, com.netgrif.application.engine.importer.model.BaseEvent imported) { + return imported.getActions().stream() .filter(actions -> actions.getPhase().equals(phase)) - .flatMap(actions -> actions.getAction().stream() - .map(action -> { - action.setTrigger(trigger.name()); - return parseAction(fieldId, transitionId, action); - })) + .flatMap(actions -> actions.getAction().stream().map(this::createAction)) .collect(Collectors.toList()); - actionList.addAll(dataEvent.getActions().stream() - .filter(actions -> actions.getPhase().equals(phase)) - .flatMap(actions -> actions.getActionRef().stream().map(this::fromActionRef)) - .collect(Collectors.toList())); - return actionList; } - protected void addDefaultRole(Transition transition) { - if (!net.isDefaultRoleEnabled() || isDefaultRoleReferenced(transition)) { - return; + protected Action createAction(com.netgrif.application.engine.importer.model.Action importedAction) { + Action action = new Action(); + action.setImportId(buildActionId(importedAction.getId())); + action.setDefinition(importedAction.getValue()); + if (importedAction.getType() != null) { + // TODO: release/8.0.0 add attribute "type" to data set actions } - - Logic logic = new Logic(); - logic.setDelegate(true); - logic.setPerform(true); - transition.addRole(defaultRole.getStringId(), roleFactory.getPermissions(logic)); + return action; } - protected void addAnonymousRole(Transition transition) { - if (!net.isAnonymousRoleEnabled() || isAnonymousRoleReferenced(transition)) { - return; - } - - Logic logic = new Logic(); - logic.setPerform(true); - transition.addRole(anonymousRole.getStringId(), roleFactory.getPermissions(logic)); + protected DataEvent createDataEvent(com.netgrif.application.engine.importer.model.DataEvent importedEvent) { + DataEvent event = new DataEvent(); + event.setType(DataEventType.valueOf(importedEvent.getType().value().toUpperCase())); + this.addBaseEventProperties(event, importedEvent); + return event; } - protected void addDefaultPermissions() { - if (!net.isDefaultRoleEnabled() || isDefaultRoleReferencedOnNet()) { + // TODO: release/8.0.0 refactor common event creation + protected void createProcessEvent(com.netgrif.application.engine.importer.model.ProcessEvent importedEvent) { + if (importedEvent == null) { return; } - - CaseLogic logic = new CaseLogic(); - logic.setCreate(true); - logic.setDelete(true); - logic.setView(true); - net.addPermission(defaultRole.getStringId(), roleFactory.getProcessPermissions(logic)); + ProcessEvent event = new ProcessEvent(); + event.setType(ProcessEventType.valueOf(importedEvent.getType().value().toUpperCase())); + this.addBaseEventProperties(event, importedEvent); + process.addProcessEvent(event); } - protected void addAnonymousPermissions() { - if (!net.isAnonymousRoleEnabled() || isAnonymousRoleReferencedOnNet()) { + protected void createCaseEvent(com.netgrif.application.engine.importer.model.CaseEvent importedEvent) { + if (importedEvent == null) { return; } - - CaseLogic logic = new CaseLogic(); - logic.setCreate(true); - logic.setView(true); - net.addPermission(anonymousRole.getStringId(), roleFactory.getProcessPermissions(logic)); - } - - protected void addDataWithDefaultGroup(Transition transition, DataRef dataRef) throws MissingIconKeyException { - DataGroup dataGroup = new DataGroup(); - dataGroup.setImportId(transition.getImportId() + "_" + dataRef.getId() + "_" + System.currentTimeMillis()); - if (transition.getLayout() != null && transition.getLayout().getCols() != null) { - dataGroup.setLayout(new DataGroupLayout(null, transition.getLayout().getCols(), null, null, null)); - } - dataGroup.setAlignment(DataGroupAlignment.START); - dataGroup.setStretch(true); - dataGroup.addData(getField(dataRef.getId()).getStringId()); - transition.addDataGroup(dataGroup); - - addDataLogic(transition, dataRef); - addDataLayout(transition, dataRef); - addDataComponent(transition, dataRef); - } - - protected void addDataGroup(Transition transition, com.netgrif.application.engine.importer.model.DataGroup importDataGroup, int index) throws MissingIconKeyException { - DataGroup dataGroup = new DataGroup(); - - if (importDataGroup.getId() != null && importDataGroup.getId().length() > 0) { - dataGroup.setImportId(importDataGroup.getId()); - } else { - dataGroup.setImportId(transition.getImportId() + "_dg_" + index); - } - - dataGroup.setLayout(new DataGroupLayout(importDataGroup)); - - dataGroup.setTitle(toI18NString(importDataGroup.getTitle())); - dataGroup.setAlignment(importDataGroup.getAlignment() != null ? importDataGroup.getAlignment() : null); - dataGroup.setStretch(importDataGroup.isStretch()); - importDataGroup.getDataRef().forEach(dataRef -> dataGroup.addData(getField(dataRef.getId()).getStringId())); - transition.addDataGroup(dataGroup); - DataGroupLayout dataGroupLayout = dataGroup.getLayout() != null && dataGroup.getLayout().getType() != null ? dataGroup.getLayout() : null; - - for (DataRef dataRef : importDataGroup.getDataRef()) { - if (dataGroupLayout != null && dataGroupLayout.getType().equals(LayoutType.GRID) && dataRef.getLayout() == null) { - throw new IllegalArgumentException("Data ref [" + dataRef.getId() + "] of data group [" + dataGroup.getStringId() + "] in transition [" + transition.getStringId() + "] doesn't have a layout."); - } - addDataLogic(transition, dataRef); - addDataLayout(transition, dataRef); - addDataComponent(transition, dataRef); - } + CaseEvent event = new CaseEvent(); + event.setType(CaseEventType.valueOf(importedEvent.getType().value().toUpperCase())); + this.addBaseEventProperties(event, importedEvent); + process.addCaseEvent(event); } - protected void addToTransaction(Transition transition, TransactionRef transactionRef) { - Transaction transaction = getTransaction(transactionRef.getId()); - if (transaction == null) { - throw new IllegalArgumentException("Referenced transaction [" + transactionRef.getId() + "] in transition [" + transition.getTitle() + "] doesn't exist."); - } - transaction.addTransition(transition); + protected void createFunction(com.netgrif.application.engine.importer.model.Function importedFunction) { + Function function = new Function(); + function.setDefinition(importedFunction.getValue()); + function.setName(importedFunction.getName()); + function.setScope(FunctionScope.valueOf(importedFunction.getScope().name())); + process.addFunction(function); } - protected void addRoleLogic(Transition transition, RoleRef roleRef) { - Logic logic = roleRef.getLogic(); - String roleId = getRole(roleRef.getId()).getStringId(); - - if (logic == null || roleId == null) { + protected void addPredefinedRolesWithDefaultPermissions() { + // only if no positive role associations and no positive user ref associations + if (process.getProcessRolePermissions().getPermissions().values().stream() + .anyMatch(perms -> perms.containsValue(true))) { return; } - - logicValidator.checkConflictingAttributes(logic, logic.isAssigned(), logic.isAssign(), "assigned", "assign"); - logicValidator.checkDeprecatedAttributes(logic); - - if (logic.isView() != null && !logic.isView()) { - transition.addNegativeViewRole(roleId); - } - transition.addRole(roleId, roleFactory.getPermissions(logic)); + addDefaultRole(); + addAnonymousRole(); } - protected void addUserLogic(Transition transition, UserRef userRef) { - Logic logic = userRef.getLogic(); - String userRefId = userRef.getId(); - - if (logic == null || userRefId == null) { + protected void addPredefinedRolesWithDefaultPermissions(com.netgrif.application.engine.importer.model.Transition importTransition, Transition transition) { + // Don't add if positive roles or triggers or positive user refs + if ((importTransition.getRoleRef() != null && importTransition.getRoleRef().stream().anyMatch(this::hasPositivePermission)) + || (importTransition.getTrigger() != null && !importTransition.getTrigger().isEmpty())) { return; } - - logicValidator.checkConflictingAttributes(logic, logic.isAssigned(), logic.isAssign(), "assigned", "assign"); - logicValidator.checkDeprecatedAttributes(logic); - - transition.addUserRef(userRefId, roleFactory.getPermissions(logic)); + addDefaultRole(transition); + addAnonymousRole(transition); } - protected void addDataLogic(Transition transition, DataRef dataRef) { - Logic logic = dataRef.getLogic(); - try { - Field<?> field = getField(dataRef.getId()); - String fieldId = field.getStringId(); - if (logic == null || fieldId == null) { - return; - } - - DataFieldBehavior behavior = new DataFieldBehavior(); - if (logic.getBehavior() != null) { - Optional<Behavior> first = logic.getBehavior().stream().filter(this::isNotDeprecated).findFirst(); - behavior.setBehavior(FieldBehavior.fromString(first.orElse(Behavior.EDITABLE))); - behavior.setRequired(logic.getBehavior().stream().anyMatch(Behavior.REQUIRED::equals)); - behavior.setImmediate(logic.getBehavior().stream().anyMatch(Behavior.IMMEDIATE::equals)); - } - transition.setDataRefBehavior(field, behavior); - } catch (NullPointerException e) { - throw new IllegalArgumentException("Wrong dataRef id [" + dataRef.getId() + "] on transition [" + transition.getTitle() + "]", e); - } + protected void addDefaultRole() { + addSystemRole(isDefaultRoleEnabled, defaultProcessRole); } - // TODO: release/8.0.0 Behavior REQ,IMM,OPT deprecated - private boolean isNotDeprecated(Behavior behavior) { - return !Behavior.REQUIRED.equals(behavior) && !Behavior.IMMEDIATE.equals(behavior) && !Behavior.OPTIONAL.equals(behavior); + protected void addDefaultRole(Transition transition) { + addSystemRole(transition, isDefaultRoleEnabled, defaultProcessRole); } - protected void addDataLayout(Transition transition, DataRef dataRef) { - Layout layout = dataRef.getLayout(); - try { - Field<?> field = getField(dataRef.getId()); - String fieldId = field.getStringId(); - if (layout == null || fieldId == null) { - return; - } - - String template = DEFAULT_FIELD_TEMPLATE; - if (layout.getTemplate() != null) { - template = layout.getTemplate().toString(); - } - - String appearance = DEFAULT_FIELD_APPEARANCE; - if (layout.getAppearance() != null) { - appearance = layout.getAppearance().toString(); - } - - String alignment = DEFAULT_FIELD_ALIGNMENT; - if (layout.getAlignment() != null) { - alignment = layout.getAlignment().value(); - } - - FieldLayout fieldLayout = new FieldLayout(layout.getX(), layout.getY(), layout.getRows(), layout.getCols(), layout.getOffset(), template, appearance, alignment); - transition.setDataRefLayout(field, fieldLayout); - } catch (NullPointerException e) { - throw new IllegalArgumentException("Wrong dataRef id [" + dataRef.getId() + "] on transition [" + transition.getTitle() + "]", e); - } + protected void addAnonymousRole() { + addSystemRole(isAnonymousRoleEnabled, anonymousProcessRole); } - // TODO: release/8.0.0 check merge - /*protected void addDataComponent(Transition transition, DataRef dataRef) throws MissingIconKeyException { - String fieldId = getField(dataRef.getId()).getStringId(); - Component component = null; - if ((dataRef.getComponent()) != null) { - component = componentFactory.buildComponent(dataRef.getComponent(), this, getField(dataRef.getId())); - } - transition.addDataSet(fieldId, null, null, null, component); - }*/ - protected void addDataComponent(Transition transition, DataRef dataRef) throws MissingIconKeyException { - Field<?> field = getField(dataRef.getId()); - Component component; - if ((dataRef.getComponent()) == null) { - component = field.getComponent(); - } else { - component = componentFactory.buildComponent(dataRef.getComponent(), this, field); - } - transition.setDataRefComponent(field, component); + protected void addAnonymousRole(Transition transition) { + addSystemRole(transition, isAnonymousRoleEnabled, anonymousProcessRole); } - protected Map<DataEventType, DataEvent> buildEvents(String fieldId, List<com.netgrif.application.engine.importer.model.DataEvent> events, String transitionId) { - Map<DataEventType, DataEvent> parsedEvents = new HashMap<>(); - - List<com.netgrif.application.engine.importer.model.DataEvent> filteredEvents = events.stream() - .filter(event -> DataEventType.GET.toString().equalsIgnoreCase(event.getType().toString())) - .collect(Collectors.toList()); - if (!filteredEvents.isEmpty()) { - parsedEvents.put(DataEventType.GET, parseDataEvent(fieldId, filteredEvents, transitionId)); - } - - filteredEvents = events.stream().filter(event -> DataEventType.SET.toString().equalsIgnoreCase(event.getType().toString())) - .collect(Collectors.toList()); - if (!filteredEvents.isEmpty()) { - parsedEvents.put(DataEventType.SET, parseDataEvent(fieldId, filteredEvents, transitionId)); + protected void addSystemRole(boolean isEnabled, Role role) { + if (!isEnabled || process.getProcessRolePermissions().containsKey(role.getStringId())) { + return; } - return parsedEvents; + com.netgrif.application.engine.importer.model.CasePermission permissions = new com.netgrif.application.engine.importer.model.CasePermission(); + permissions.setCreate(true); + permissions.setDelete(true); // TODO: release/8.0.0 anonymous can delete + permissions.setView(true); + process.addProcessRolePermission(role.getStringId(), permissionFactory.buildProcessPermissions(permissions)); } - protected com.netgrif.application.engine.petrinet.domain.events.DataEvent parseDataEvent(String fieldId, List<com.netgrif.application.engine.importer.model.DataEvent> events, String transitionId) { - com.netgrif.application.engine.petrinet.domain.events.DataEvent dataEvent = new com.netgrif.application.engine.petrinet.domain.events.DataEvent(); - events.forEach(event -> { - dataEvent.setType(event.getType() == DataEventType.GET ? DataEventType.GET : DataEventType.SET); - if (dataEvent.getId() == null) { - dataEvent.setId(event.getId()); - } - if (dataEvent.getMessage() == null && event.getMessage() != null) { - dataEvent.setMessage(toI18NString(event.getMessage())); - } - event.getActions().forEach(action -> { - EventPhaseType phaseType = action.getPhase(); - if (action.getPhase() == null) { - phaseType = event.getType().toString().equalsIgnoreCase(DataEventType.GET.toString()) ? EventPhaseType.PRE : EventPhaseType.POST; - } - List<Action> parsedPhaseActions = parsePhaseActions(fieldId, phaseType, dataEvent.getType(), transitionId, event); - if (phaseType == EventPhaseType.PRE) { - dataEvent.getPreActions().addAll(parsedPhaseActions); - } else { - dataEvent.getPostActions().addAll(parsedPhaseActions); - } - }); - }); - return dataEvent; - } + protected void addSystemRole(Transition transition, boolean isEnabled, Role role) { + if (!isEnabled || transition.getProcessRolePermissions().containsKey(role.getStringId())) { + return; + } - protected List<Action> buildActions(List<com.netgrif.application.engine.importer.model.Action> imported, String fieldId, String transitionId) { - return imported.stream() - .map(action -> parseAction(fieldId, transitionId, action)) - .collect(Collectors.toList()); + com.netgrif.application.engine.importer.model.TaskPermission permissions = new com.netgrif.application.engine.importer.model.TaskPermission(); + permissions.setPerform(true); + transition.addProcessRolePermission(role.getStringId(), permissionFactory.buildTaskPermissions(permissions)); } - protected Action parseAction(String transitionId, com.netgrif.application.engine.importer.model.Action action) { - if (action.getValue().contains("f.this")) { - throw new IllegalArgumentException("Event action can not reference field using 'this'"); + protected void createProcessPermissions(com.netgrif.application.engine.importer.model.CaseRoleRef roleRef) { + if (roleRef.getType() == RoleType.CASE) { + createProcessPermissionsForCaseRole(roleRef); + return; } - return parseAction(null, transitionId, action); + com.netgrif.application.engine.importer.model.CasePermission permissions = roleRef.getPermission(); + Optional<Role> roleOpt = findRoleOrWarn(permissions, roleRef.getId()); + roleOpt.ifPresent((role) -> process.addProcessRolePermission(role.getStringId(), permissionFactory.buildProcessPermissions(permissions))); } - protected Action parseAction(String fieldId, String transitionId, com.netgrif.application.engine.importer.model.Action importedAction) { - if (fieldId != null && importedAction.getTrigger() == null) { - throw new IllegalArgumentException("Data field action [" + importedAction.getValue() + "] doesn't have trigger"); - } - try { - Action action = createAction(importedAction); - parseIds(fieldId, transitionId, importedAction, action); - actions.put(action.getImportId(), action); - return action; - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Error parsing ids of action [" + importedAction.getValue() + "]", e); + protected void createProcessPermissionsForCaseRole(com.netgrif.application.engine.importer.model.CaseRoleRef roleRef) { + com.netgrif.application.engine.importer.model.CasePermission permissions = roleRef.getPermission(); + String userListId = roleRef.getId(); + if (permissions == null || userListId == null) { + log.warn("Case role has missing permissions or user list id"); + return; } + process.addCaseRolePermission(userListId, permissionFactory.buildProcessPermissions(permissions)); } - // TODO: release/8.0.0 add atribute "type" to set actions - protected Action createAction(com.netgrif.application.engine.importer.model.Action importedAction) { - Action action = new Action(); - if (importedAction.getTrigger() != null) { - action.setTrigger(DataEventType.fromValue(importedAction.getTrigger().toLowerCase())); + protected void createTaskPermissions(Transition transition, com.netgrif.application.engine.importer.model.RoleRef roleRef) { + if (roleRef.getType() == RoleType.CASE) { + createTaskPermissionsForCaseRole(transition, roleRef); + return; } - action.setImportId(buildActionId(importedAction.getId())); - return action; + com.netgrif.application.engine.importer.model.TaskPermission permissions = roleRef.getPermission(); + Optional<Role> roleOpt = findRoleOrWarn(permissions, roleRef.getId()); + roleOpt.ifPresent((role) -> transition.addProcessRolePermission(role.getStringId(), permissionFactory.buildTaskPermissions(permissions))); } - protected String buildActionId(String importedActionId) { - String sanitizedImportedId; - if (importedActionId != null) { - if (actions.containsKey(this.net.getIdentifier() + "-" + importedActionId)) { - throw new IllegalArgumentException("Duplicate action id, action with id [" + importedActionId + "] already exists in petri net with identifier [" + this.net.getIdentifier() + "]"); - } - sanitizedImportedId = importedActionId; - } else { - sanitizedImportedId = new ObjectId().toString(); + protected void createTaskPermissionsForCaseRole(Transition transition, com.netgrif.application.engine.importer.model.RoleRef roleRef) { + com.netgrif.application.engine.importer.model.TaskPermission permissions = roleRef.getPermission(); + String userListId = roleRef.getId(); + if (permissions == null || userListId == null) { + log.warn("Case role has missing permissions or user list id on transition [{}]", transition.getImportId()); + return; } - return this.net.getIdentifier() + "-" + sanitizedImportedId; + transition.addCaseRolePermission(userListId, permissionFactory.buildTaskPermissions(permissions)); } - protected void parseIds(String fieldId, String transitionId, com.netgrif.application.engine.importer.model.Action importedAction, Action action) { - String definition = importedAction.getValue(); - action.setDefinition(definition); - - if (containsParams(definition)) { - parseParamsAndObjectIds(action, fieldId, transitionId); + protected Optional<Role> findRoleOrWarn(Object permissions, String roleImportId) { + if (permissions == null) { + log.warn("Referenced role with id [{}] has missing permissions", roleImportId); + return Optional.empty(); } - actionValidator.validateAction(action.getDefinition()); - } - - protected void parseParamsAndObjectIds(Action action, String fieldId, String transitionId) { - String[] actionParts = action.getDefinition().split(";", 2); - action.setDefinition(actionParts[1]); - parseObjectIds(action, fieldId, transitionId, actionParts[0]); - } - - protected boolean containsParams(String definition) { - return definition.matches("[\\W\\w\\s]*[\\w]*:[\\s]*[ft].[\\w]+;[\\w\\W\\s]*"); - } - - protected void parseObjectIds(Action action, String fieldId, String transitionId, String definition) { - try { - Map<String, String> ids = parseParams(definition); - - ids.entrySet().forEach(entry -> replaceImportId(action, fieldId, transitionId, entry)); - } catch (NullPointerException e) { - throw new IllegalArgumentException("Failed to parse action: " + action, e); + Role processRole = this.findRole(roleImportId); + if (processRole == null) { + log.warn("Referenced role with id [{}] was not found in application", roleImportId); + return Optional.empty(); } + return Optional.of(processRole); } - protected void replaceImportId(Action action, String fieldId, String transitionId, Map.Entry<String, String> entry) { - String[] parts = entry.getValue().split("[.]"); - if (parts.length != 2) { - throw new IllegalArgumentException("Can not parse id of " + entry.getValue()); - } - String key = parts[0]; - String importId = parts[1]; - String paramName = entry.getKey().trim(); - - if (importId.startsWith("this")) { - if (Objects.equals(key.trim(), FIELD_KEYWORD)) { - action.addFieldId(paramName, fieldId); - return; - } - if (Objects.equals(key.trim(), TRANSITION_KEYWORD)) { - action.addTransitionId(paramName, transitionId); - return; - } - } - if (Objects.equals(key.trim(), FIELD_KEYWORD)) { - action.addFieldId(paramName, getFieldId(importId)); - return; - } - if (Objects.equals(key.trim(), TRANSITION_KEYWORD)) { - action.addTransitionId(paramName, importId); - return; - } - throw new IllegalArgumentException("Object " + key + "." + importId + " not supported"); + protected boolean hasPositivePermission(com.netgrif.application.engine.importer.model.PermissionRef permissionRef) { + com.netgrif.application.engine.importer.model.TaskPermission logic = permissionRef.getPermission(); + return isAnyTrue( + logic.isPerform(), + logic.isView(), + logic.isAssign(), + logic.isCancel(), + logic.isFinish(), + logic.isReassign(), + logic.isViewDisabled() + ); } - protected Map<String, String> parseParams(String definition) { - List<String> params = Arrays.asList(definition.split(",")); - return params.stream() - .map(param -> param.split(":")) - .collect(Collectors.toMap(o -> o[0], o -> o[1])); + protected boolean isAnyTrue(Boolean... permissions) { + return Arrays.stream(permissions).anyMatch(this::isTrue); } - protected String getFieldId(String importId) { - try { - return getField(importId).getStringId(); - } catch (Exception e) { - throw new IllegalArgumentException("Object f." + importId + " does not exists"); + protected String buildActionId(String actionId) { + if (actionId == null) { + actionId = new ObjectId().toString(); } + // TODO: release/8.0.0 optimize ids of actions to not use strings + return this.process.getIdentifier() + "-" + actionId; } - protected void addTrigger(Transition transition, com.netgrif.application.engine.importer.model.Trigger importTrigger) { - Trigger trigger = triggerFactory.buildTrigger(importTrigger); - - transition.addTrigger(trigger); + protected void createTrigger(Transition transition, com.netgrif.application.engine.importer.model.Trigger importTrigger) { + transition.addTrigger(triggerFactory.buildTrigger(importTrigger)); } protected void createPlace(com.netgrif.application.engine.importer.model.Place importPlace) { Place place = new Place(); place.setImportId(importPlace.getId()); - if (importPlace.isStatic() == null) { - place.setIsStatic(importPlace.isIsStatic()); - } else { - place.setIsStatic(importPlace.isStatic()); - } place.setTokens(importPlace.getTokens()); - place.setPosition(importPlace.getX(), importPlace.getY()); - place.setTitle(importPlace.getLabel() != null ? toI18NString(importPlace.getLabel()) : new I18nString("")); - - net.addPlace(place); - places.put(importPlace.getId(), place); + place.setTitle(toI18NString(importPlace.getTitle())); + createProperties(importPlace.getProperties(), place.getProperties()); + process.addPlace(place); } - protected void createRole(Role importRole) { - if (importRole.getId().equals(ProcessRole.DEFAULT_ROLE)) { - throw new IllegalArgumentException("Role ID '" + ProcessRole.DEFAULT_ROLE + "' is a reserved identifier, roles with this ID cannot be defined!"); - } - - if (importRole.getId().equals(ProcessRole.ANONYMOUS_ROLE)) { - throw new IllegalArgumentException("Role ID '" + ProcessRole.ANONYMOUS_ROLE + "' is a reserved identifier, roles with this ID cannot be defined!"); + protected void createRole(com.netgrif.application.engine.importer.model.Role importRole) { + String importId = importRole.getId(); + if (roleService.existsProcessRoleByImportId(importId)) { + return; } - ProcessRole role = new ProcessRole(); - Map<EventType, com.netgrif.application.engine.petrinet.domain.events.Event> events = createEventsMap(importRole.getEvent()); - - role.setImportId(importRole.getId()); - role.setEvents(events); - - if (importRole.getName() == null) { - role.setName(toI18NString(importRole.getTitle())); - } else { - role.setName(toI18NString(importRole.getName())); + ProcessRole processRole = new ProcessRole(importRole.getId()); + processRole.setTitle(toI18NString(importRole.getTitle())); + if (importRole.getEvent() != null) { + importRole.getEvent().forEach(event -> processRole.addEvent(createEvent(event))); } - role.setId(new ObjectId()); - - role.setNetId(net.getStringId()); - net.addRole(role); - roles.put(importRole.getId(), role); - } - - protected Map<EventType, com.netgrif.application.engine.petrinet.domain.events.Event> createEventsMap(List<com.netgrif.application.engine.importer.model.Event> events) { - Map<EventType, com.netgrif.application.engine.petrinet.domain.events.Event> finalEvents = new HashMap<>(); - events.forEach(event -> - finalEvents.put(EventType.valueOf(event.getType().value().toUpperCase()), addEvent(null, event)) - ); - - return finalEvents; - } - - protected Map<ProcessEventType, com.netgrif.application.engine.petrinet.domain.events.ProcessEvent> createProcessEventsMap(List<com.netgrif.application.engine.importer.model.ProcessEvent> events) { - Map<ProcessEventType, com.netgrif.application.engine.petrinet.domain.events.ProcessEvent> finalEvents = new HashMap<>(); - events.forEach(event -> - finalEvents.put(ProcessEventType.valueOf(event.getType().value().toUpperCase()), addProcessEvent(event)) - ); - - return finalEvents; + result.addRole(processRole); } - protected Map<CaseEventType, com.netgrif.application.engine.petrinet.domain.events.CaseEvent> createCaseEventsMap(List<com.netgrif.application.engine.importer.model.CaseEvent> events) { - Map<CaseEventType, com.netgrif.application.engine.petrinet.domain.events.CaseEvent> finalEvents = new HashMap<>(); - events.forEach(event -> - finalEvents.put(CaseEventType.valueOf(event.getType().value().toUpperCase()), addCaseEvent(event)) - ); + protected com.netgrif.application.engine.petrinet.domain.policies.AssignPolicy toAssignPolicy(com.netgrif.application.engine.importer.model.AssignPolicy policy) { + if (policy == null || policy.value() == null) { + return com.netgrif.application.engine.petrinet.domain.policies.AssignPolicy.MANUAL; + } - return finalEvents; + return com.netgrif.application.engine.petrinet.domain.policies.AssignPolicy.valueOf(policy.value().toUpperCase()); } - protected void createTransaction(com.netgrif.application.engine.importer.model.Transaction importTransaction) { - Transaction transaction = new Transaction(); - transaction.setTitle(toI18NString(importTransaction.getTitle())); - transaction.setImportId(importTransaction.getId()); + protected com.netgrif.application.engine.petrinet.domain.policies.FinishPolicy toFinishPolicy(com.netgrif.application.engine.importer.model.FinishPolicy policy) { + if (policy == null || policy.value() == null) { + return com.netgrif.application.engine.petrinet.domain.policies.FinishPolicy.MANUAL; + } - net.addTransaction(transaction); - transactions.put(importTransaction.getId(), transaction); + return com.netgrif.application.engine.petrinet.domain.policies.FinishPolicy.valueOf(policy.value().toUpperCase()); } - protected Node getNode(String id) { - if (places.containsKey(id)) { - return getPlace(id); - } else if (transitions.containsKey(id)) { - return getTransition(id); + protected void createProperties(com.netgrif.application.engine.importer.model.Properties propertiesXml, UniqueKeyMapWrapper<String> properties) { + if (propertiesXml == null) { + return; } - throw new IllegalArgumentException("Node with id [" + id + "] not found."); + propertiesXml.getProperty().forEach(property -> properties.put(property.getKey(), property.getValue())); } - public I18nString toI18NString(I18NStringType imported) { - if (imported == null) { - return null; + protected void resolveLayoutContainer(com.netgrif.application.engine.importer.model.Transition importTransition, Transition transition) { + if (importTransition.getFlex() != null && importTransition.getGrid() != null) { + throw new IllegalArgumentException(String.format("Found Flex and Grid container together in Transition {%s}", + importTransition.getId())); } - String key = imported.getValue(); - if (imported.getName() != null) { - key = imported.getName(); - } - if (imported instanceof Option) { - key = ((Option) imported).getKey(); + if (importTransition.getFlex() != null) { + transition.setLayoutContainer(getFlexLayoutContainer(importTransition.getFlex(), transition, 0)); } - I18nString string = i18n.getOrDefault(imported.getName(), new I18nString(key, imported.getValue())); - if (string.getDefaultValue() == null) { - string.setDefaultValue(imported.getValue()); + if (importTransition.getGrid() != null) { + transition.setLayoutContainer(getGridLayoutContainer(importTransition.getGrid(), transition, 0)); } - return string; } - protected void addPredefinedRolesWithDefaultPermissions(com.netgrif.application.engine.importer.model.Transition importTransition, Transition transition) { - // Don't add if role or trigger mapping - for (Mapping mapping : document.getMapping()) { - if (Objects.equals(mapping.getTransitionRef(), importTransition.getId()) - && (mapping.getRoleRef() != null && !mapping.getRoleRef().isEmpty()) - && (mapping.getTrigger() != null && !mapping.getTrigger().isEmpty()) - ) { - return; + protected LayoutContainer getFlexLayoutContainer(FlexContainer importedFlexContainer, Transition transition, int depth) { + LayoutContainer layoutContainer = new LayoutContainer(); + layoutContainer.setImportId(importedFlexContainer.getId()); + layoutContainer.setLayoutType(LayoutObjectType.FLEX); + + Map<String, String> layoutContainerProperties = new HashMap<>(depth == 0 ? flexConfiguration.getRoot() : flexConfiguration.getContainer()); + if (importedFlexContainer.getProperties() != null) { + for (java.lang.reflect.Field containerPropertyField : importedFlexContainer.getProperties().getClass().getDeclaredFields()) { + try { + resolveFieldProperty(containerPropertyField, layoutContainerProperties, importedFlexContainer.getProperties()); + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { + throw new IllegalArgumentException(String.format("Unexpected property in Flex Container {%s}", + importedFlexContainer.getId())); + } } } - // Don't add if positive roles or triggers or positive user refs - if ((importTransition.getRoleRef() != null && importTransition.getRoleRef().stream().anyMatch(this::hasPositivePermission)) - || (importTransition.getTrigger() != null && !importTransition.getTrigger().isEmpty()) - || (importTransition.getUsersRef() != null && importTransition.getUsersRef().stream().anyMatch(this::hasPositivePermission)) - || (importTransition.getUserRef() != null && importTransition.getUserRef().stream().anyMatch(this::hasPositivePermission))) { - return; - } - - addDefaultRole(transition); - addAnonymousRole(transition); - } - - protected boolean hasPositivePermission(PermissionRef permissionRef) { - return (permissionRef.getLogic().isPerform() != null && permissionRef.getLogic().isPerform()) - || (permissionRef.getLogic().isCancel() != null && permissionRef.getLogic().isCancel()) - || (permissionRef.getLogic().isView() != null && permissionRef.getLogic().isView()) - || (permissionRef.getLogic().isAssign() != null && permissionRef.getLogic().isAssign()) - || (permissionRef.getLogic().isAssigned() != null && permissionRef.getLogic().isAssigned()) - || (permissionRef.getLogic().isFinish() != null && permissionRef.getLogic().isFinish()) - || (permissionRef.getLogic().isDelegate() != null && permissionRef.getLogic().isDelegate()); - } + layoutContainer.setProperties(layoutContainerProperties); - protected void addPredefinedRolesWithDefaultPermissions() { - // only if no positive role associations and no positive user ref associations - if (net.getPermissions().values().stream().anyMatch(perms -> perms.containsValue(true)) - || net.getUserRefs().values().stream().anyMatch(perms -> perms.containsValue(true))) { - return; + for (FlexItem flexItem : importedFlexContainer.getItem()) { + layoutContainer.addLayoutItem(getLayoutItem(importedFlexContainer.getId(), flexItem, transition, depth)); } - addDefaultPermissions(); - addAnonymousPermissions(); - } - - protected boolean isDefaultRoleReferenced(Transition transition) { - return transition.getRoles().containsKey(defaultRole.getStringId()); - } - - protected boolean isDefaultRoleReferencedOnNet() { - return net.getPermissions().containsKey(defaultRole.getStringId()); - } - - protected boolean isAnonymousRoleReferenced(Transition transition) { - return transition.getRoles().containsKey(anonymousRole.getStringId()); - } - - protected boolean isAnonymousRoleReferencedOnNet() { - return net.getPermissions().containsKey(anonymousRole.getStringId()); + return layoutContainer; } - protected AssignPolicy toAssignPolicy(com.netgrif.application.engine.importer.model.AssignPolicy policy) { - if (policy == null || policy.value() == null) { - return AssignPolicy.MANUAL; - } - - return AssignPolicy.valueOf(policy.value().toUpperCase()); - } + protected LayoutContainer getGridLayoutContainer(GridContainer importedGridContainer, Transition transition, int depth) { + LayoutContainer layoutContainer = new LayoutContainer(); + layoutContainer.setImportId(importedGridContainer.getId()); + layoutContainer.setLayoutType(LayoutObjectType.GRID); - protected DataFocusPolicy toDataFocusPolicy(com.netgrif.application.engine.importer.model.DataFocusPolicy policy) { - if (policy == null || policy.value() == null) { - return DataFocusPolicy.MANUAL; + Map<String, String> layoutProperties = new HashMap<>(depth == 0 ? gridConfiguration.getRoot() : gridConfiguration.getContainer()); + if (importedGridContainer.getProperties() != null) { + for (java.lang.reflect.Field field : importedGridContainer.getProperties().getClass().getDeclaredFields()) { + try { + resolveFieldProperty(field, layoutProperties, importedGridContainer.getProperties()); + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { + throw new IllegalArgumentException(String.format("Unexpected property in Grid Container {%s}", + importedGridContainer.getId())); + } + } } + layoutContainer.setProperties(layoutProperties); - return DataFocusPolicy.valueOf(policy.value().toUpperCase()); - } - - protected FinishPolicy toFinishPolicy(com.netgrif.application.engine.importer.model.FinishPolicy policy) { - if (policy == null || policy.value() == null) { - return FinishPolicy.MANUAL; + for (GridItem gridItem : importedGridContainer.getItem()) { + layoutContainer.addLayoutItem(getLayoutItem(importedGridContainer.getId(), gridItem, transition, depth)); } - return FinishPolicy.valueOf(policy.value().toUpperCase()); + return layoutContainer; } - public ProcessRole getRole(String id) { - if (id.equals(ProcessRole.DEFAULT_ROLE)) { - return defaultRole; + private LayoutItem getLayoutItem(String containerId, com.netgrif.application.engine.importer.model.LayoutItem importedLayoutItem, Transition transition, int depth) { + if (BooleanUtils.toInteger(importedLayoutItem.getFlex() != null) + BooleanUtils.toInteger(importedLayoutItem.getGrid() != null) + BooleanUtils.toInteger(importedLayoutItem.getDataRef() != null) > 1) { + throw new IllegalArgumentException(String.format("Found Flex/Grid/DataRef together in Layout Container {%s}", + containerId)); } + LayoutItem layoutItem = new LayoutItem(); + layoutItem.setLayoutType(importedLayoutItem instanceof GridItem ? LayoutObjectType.GRID : LayoutObjectType.FLEX); - if (id.equals(ProcessRole.ANONYMOUS_ROLE)) { - return anonymousRole; + boolean isFlex = importedLayoutItem instanceof FlexItem; + Map<String, String> layoutItemProperties = isFlex ? new HashMap<>(flexConfiguration.getChildren()) : new HashMap<>(gridConfiguration.getChildren()); + Object itemProperties = !isFlex ? ((GridItem) importedLayoutItem).getProperties() : ((FlexItem) importedLayoutItem).getProperties(); + if (itemProperties != null) { + for (java.lang.reflect.Field itemPropertyField : itemProperties.getClass().getDeclaredFields()) { + try { + resolveFieldProperty(itemPropertyField, layoutItemProperties, itemProperties); + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { + throw new IllegalArgumentException(String.format("Unexpected property in Grid Item of Grid Container {%s}", + containerId)); + } + } } + layoutItem.setProperties(layoutItemProperties); - ProcessRole role = roles.get(id); - if (role == null) { - throw new IllegalArgumentException("Role " + id + " not found"); + if (importedLayoutItem.getFlex() != null) { + layoutItem.setContainer(getFlexLayoutContainer(importedLayoutItem.getFlex(), transition, depth + 1)); + } else if (importedLayoutItem.getGrid() != null) { + layoutItem.setContainer(getGridLayoutContainer(importedLayoutItem.getGrid(), transition, depth + 1)); + } else if (importedLayoutItem.getDataRef() != null) { + layoutItem.setDataRefId(resolveDataRef(importedLayoutItem.getDataRef(), transition).getFieldId()); } - return role; + return layoutItem; } - public Field<?> getField(String id) { - Field<?> field = fields.get(id); - if (field == null) { - throw new IllegalArgumentException("Field " + id + " not found"); + protected void resolveFieldProperty(java.lang.reflect.Field field, Map<String, String> layoutProperties, Object containerProperties) + throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { + String propertyName = field.getAnnotation(XmlElement.class) == null || field.getAnnotation(XmlElement.class).name().equals("##default") + ? field.getName() + : field.getAnnotation(XmlElement.class).name(); + field.setAccessible(true); + if (field.get(containerProperties) == null) { + return; } - return field; - } - - public Transition getTransition(String id) { - Transition transition = transitions.get(id); - if (transition == null) { - throw new IllegalArgumentException("Transition " + id + " not found"); + if (field.getType().equals(String.class) || field.getType().equals(Integer.class)) { + layoutProperties.put(propertyName, field.get(containerProperties).toString()); + } else { + Method valueMethod = field.get(containerProperties).getClass().getMethod("value"); + layoutProperties.put(propertyName, valueMethod.invoke(field.get(containerProperties)).toString()); } - return transition; } - public Place getPlace(String id) { - Place place = places.get(id); - if (place == null) { - throw new IllegalArgumentException("Place " + id + " not found"); + protected com.netgrif.application.engine.petrinet.domain.DataRef resolveDataRef(com.netgrif.application.engine.importer.model.DataRef importedDataRef, Transition transition) { + String fieldId = importedDataRef.getId(); + Field<?> field = process.getField(fieldId).orElseThrow(() -> + new IllegalArgumentException(String.format("Data field with id [%s] doesn't exist. DataRef cannot be resolved.", fieldId))); + com.netgrif.application.engine.petrinet.domain.DataRef dataRef = new com.netgrif.application.engine.petrinet.domain.DataRef(field); + if (!transition.getDataSet().containsKey(fieldId)) { + transition.getDataSet().put(fieldId, dataRef); + } else { + throw new IllegalArgumentException(String.format("Field with id [%s] occurs multiple times in transition [%s]", + fieldId, transition.getStringId())); } - return place; - } - - public Transaction getTransaction(String id) { - Transaction transaction = transactions.get(id); - if (transaction == null) { - throw new IllegalArgumentException("Transaction " + id + " not found"); + if (importedDataRef.getEvent() != null) { + importedDataRef.getEvent().forEach(event -> dataRef.addEvent(createDataEvent(event))); } - return transaction; + addDataLogic(field, transition, importedDataRef, dataRef); + addDataComponent(field, importedDataRef, dataRef); + return dataRef; } - public I18nString getI18n(String id) { - return i18n.get(id); - } + protected void addDataLogic(Field<?> field, Transition transition, DataRef importedDataRef, com.netgrif.application.engine.petrinet.domain.DataRef dataRef) { + DataRefLogic logic = importedDataRef.getLogic(); + try { + String fieldId = field.getStringId(); + if (logic == null || fieldId == null) { + return; + } - protected static void copyInputStreamToFile(InputStream inputStream, File file) throws IOException { - try (FileOutputStream outputStream = new FileOutputStream(file)) { - int read; - byte[] bytes = new byte[1024]; - while ((read = inputStream.read(bytes)) != -1) { - outputStream.write(bytes, 0, read); + DataFieldBehavior behavior = new DataFieldBehavior(); + if (logic.getBehavior() != null) { + behavior.setBehavior(FieldBehavior.fromXml(logic.getBehavior())); + behavior.setRequired(logic.isRequired() != null ? logic.isRequired() : false); + behavior.setImmediate(logic.isImmediate() != null ? logic.isImmediate() : false); } + dataRef.setBehavior(behavior); + field.setBehavior(transition.getImportId(), behavior); + } catch (NullPointerException e) { + throw new IllegalArgumentException(String.format("Wrong dataRef id [%s] on transition [%s]", + importedDataRef.getId(), transition.getTitle()), e); } } - protected void setMetaData() throws MissingPetriNetMetaDataException { - List<String> missingMetaData = new ArrayList<>(); - if (document.getId() != null) { - net.setImportId(document.getId()); - net.setIdentifier(document.getId()); - } else { - missingMetaData.add("<id>"); - } - if (document.getTitle() != null) { - net.setTitle(toI18NString(document.getTitle())); - } else { - missingMetaData.add("<title>"); - } - if (document.getInitials() != null) { - net.setInitials(document.getInitials()); - } else { - missingMetaData.add("<initials>"); + protected void addDataComponent(Field<?> field, DataRef importedDataRef, com.netgrif.application.engine.petrinet.domain.DataRef dataRef) throws MissingIconKeyException { + Component component = field.getComponent(); + if (importedDataRef.getComponent() != null) { + component = createComponent(importedDataRef.getComponent()); } + dataRef.setComponent(component); + } - if (!missingMetaData.isEmpty()) { - throw new MissingPetriNetMetaDataException(missingMetaData); - } + public Component createComponent(com.netgrif.application.engine.importer.model.Component importedComponent) { + Component component = new Component(importedComponent.getId()); + createProperties(importedComponent.getProperties(), component.getProperties()); + return component; } - protected Map<String, String> buildTagsMap(List<Tag> tagsList) { - Map<String, String> tags = new HashMap<>(); - if (tagsList != null) { - tagsList.forEach(tag -> { - tags.put(tag.getKey(), tag.getValue()); - }); - } - return tags; + protected boolean isTrue(Boolean permission) { + return (permission != null && permission); + } + + protected Role findRole(String importId) { + return result.getRoles().getOrDefault(importId, roleService.findProcessRoleByImportId(importId)); } } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/ImporterProperties.java b/src/main/java/com/netgrif/application/engine/importer/service/ImporterProperties.java new file mode 100644 index 00000000000..228a4cd22d9 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/ImporterProperties.java @@ -0,0 +1,33 @@ +package com.netgrif.application.engine.importer.service; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component +@ConfigurationProperties(prefix = "nae.importer") +public class ImporterProperties { + + /** + * Whether a process should be validated and checked for deprecated attributes and code. + */ + private boolean validateProcess = true; + + /** + * Whether actions should be evaluated ahead of time during the import. Turn off for faster import in exchange for + * a slower on-demand evaluation of actions. + */ + private boolean evaluateActions = true; + + /** + * Whether functions should be evaluated ahead of time during the import. Turn off for faster import in exchange for + * a slower on-demand evaluation of functions. + */ + private boolean evaluateFunctions = true; + + /** + * Process identifier of the Object process used as default parent process. + */ + private String objectProcess; +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/PermissionFactory.java b/src/main/java/com/netgrif/application/engine/importer/service/PermissionFactory.java new file mode 100644 index 00000000000..2040c548a9a --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/PermissionFactory.java @@ -0,0 +1,49 @@ +package com.netgrif.application.engine.importer.service; + + +import com.netgrif.application.engine.authorization.domain.permissions.CasePermission; +import com.netgrif.application.engine.authorization.domain.permissions.TaskPermission; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +@Component +public class PermissionFactory { + + public Map<CasePermission, Boolean> buildProcessPermissions(com.netgrif.application.engine.importer.model.CasePermission modelPermissions) { + Map<CasePermission, Boolean> permissions = new HashMap<>(); + addPermission(permissions, modelPermissions.isCreate(), CasePermission.CREATE); + addPermission(permissions, modelPermissions.isDelete(), CasePermission.DELETE); + addPermission(permissions, modelPermissions.isView(), CasePermission.VIEW); + return permissions; + } + + public Map<TaskPermission, Boolean> buildTaskPermissions(com.netgrif.application.engine.importer.model.TaskPermission modelPermissions) { + Map<TaskPermission, Boolean> permissions = new HashMap<>(); + addPerform(permissions, modelPermissions); + addPermission(permissions, modelPermissions.isView(), TaskPermission.VIEW); + addPermission(permissions, modelPermissions.isAssign(), TaskPermission.ASSIGN); + addPermission(permissions, modelPermissions.isCancel(), TaskPermission.CANCEL); + addPermission(permissions, modelPermissions.isFinish(), TaskPermission.FINISH); + addPermission(permissions, modelPermissions.isReassign(), TaskPermission.REASSIGN); + addPermission(permissions, modelPermissions.isViewDisabled(), TaskPermission.VIEW_DISABLED); + return permissions; + } + + private void addPerform(Map<TaskPermission, Boolean> permissions, com.netgrif.application.engine.importer.model.TaskPermission roleLogic) { + if (roleLogic.isPerform() == null) { + return; + } + for (TaskPermission permission : TaskPermission.values()) { + permissions.put(permission, roleLogic.isPerform()); + } + } + + private <T> void addPermission(Map<T, Boolean> permissions, Boolean permission, T rolePermission) { + if (permission == null) { + return; + } + permissions.put(rolePermission, permission); + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/importer/service/RoleFactory.java b/src/main/java/com/netgrif/application/engine/importer/service/RoleFactory.java deleted file mode 100644 index 411a4eb4f66..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/RoleFactory.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.netgrif.application.engine.importer.service; - - -import com.netgrif.application.engine.importer.model.CaseLogic; -import com.netgrif.application.engine.importer.model.Logic; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.petrinet.domain.Transition; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository; -import com.netgrif.application.engine.petrinet.domain.roles.RolePermission; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.Map; - -@Component -public class RoleFactory { - - @Autowired - private ProcessRoleRepository repository; - - Map<RolePermission, Boolean> getPermissions(Logic roleLogic) { - Map<RolePermission, Boolean> permissions = new HashMap<>(); - - addPerform(permissions, roleLogic); - addFinish(permissions, roleLogic); - addDelegate(permissions, roleLogic); - addCancel(permissions, roleLogic); - addAssign(permissions, roleLogic); - addView(permissions, roleLogic); - - return permissions; - } - - Map<ProcessRolePermission, Boolean> getProcessPermissions(CaseLogic roleLogic) { - Map<ProcessRolePermission, Boolean> permissions = new HashMap<>(); - - addCreate(permissions, roleLogic); - addDelete(permissions, roleLogic); - addCaseView(permissions, roleLogic); - - return permissions; - } - - private void addPerform(Map<RolePermission, Boolean> permissions, Logic roleLogic) { - if (roleLogic.isPerform() != null) { - permissions.put(RolePermission.ASSIGN, roleLogic.isPerform()); - permissions.put(RolePermission.CANCEL, roleLogic.isPerform()); - permissions.put(RolePermission.FINISH, roleLogic.isPerform()); - permissions.put(RolePermission.VIEW, roleLogic.isPerform()); - permissions.put(RolePermission.SET, roleLogic.isPerform()); - } - } - - private void addDelegate(Map<RolePermission, Boolean> permissions, Logic roleLogic) { - if (roleLogic.isDelegate() != null) { - permissions.put(RolePermission.DELEGATE, roleLogic.isDelegate()); - } - } - - private void addCancel(Map<RolePermission, Boolean> permissions, Logic roleLogic) { - if (roleLogic.isCancel() != null) { - permissions.put(RolePermission.CANCEL, roleLogic.isCancel()); - } - } - - private void addFinish(Map<RolePermission, Boolean> permissions, Logic roleLogic) { - if (roleLogic.isFinish() != null) { - permissions.put(RolePermission.FINISH, roleLogic.isFinish()); - } - } - - private void addAssign(Map<RolePermission, Boolean> permissions, Logic roleLogic) { - /* Part roleLogic.isAssigned() is deprecated and can be removed in future releases. */ - if (roleLogic.isAssigned() != null) { - permissions.put(RolePermission.ASSIGN, roleLogic.isAssigned()); - } else if (roleLogic.isAssign() != null) { - permissions.put(RolePermission.ASSIGN, roleLogic.isAssign()); - } - } - - private void addCreate(Map<ProcessRolePermission, Boolean> permissions, CaseLogic roleLogic) { - if (roleLogic.isCreate() != null) { - permissions.put(ProcessRolePermission.CREATE, roleLogic.isCreate()); - } - } - - private void addDelete(Map<ProcessRolePermission, Boolean> permissions, CaseLogic roleLogic) { - if (roleLogic.isDelete() != null) { - permissions.put(ProcessRolePermission.DELETE, roleLogic.isDelete()); - } - } - - private void addView(Map<RolePermission, Boolean> permissions, Logic roleLogic) { - if (roleLogic.isView() != null) { - permissions.put(RolePermission.VIEW, roleLogic.isView()); - } - } - - private void addCaseView(Map<ProcessRolePermission, Boolean> permissions, CaseLogic roleLogic) { - if (roleLogic.isView() != null) { - permissions.put(ProcessRolePermission.VIEW, roleLogic.isView()); - } - } - - ProcessRole transitionRole(PetriNet net, Transition transition) { - ProcessRole role = new ProcessRole(); - role.setName(transition.getImportId()); - role.setImportId(net.getStringId() + "_" + transition.getImportId()); -// role.setDescription("Default role of transition "+transition.getTitle().getDefaultValue() + " in process "+net.getTitle().getDefaultValue()); - role = repository.save(role); - return role; - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/importer/service/TriggerFactory.java b/src/main/java/com/netgrif/application/engine/importer/service/TriggerFactory.java deleted file mode 100644 index 81158078f4f..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/TriggerFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.netgrif.application.engine.importer.service; - -import com.netgrif.application.engine.workflow.domain.triggers.*; -import org.springframework.stereotype.Component; - -import java.time.format.DateTimeParseException; - -@Component -public class TriggerFactory { - - public Trigger buildTrigger(com.netgrif.application.engine.importer.model.Trigger trigger) throws IllegalArgumentException, DateTimeParseException { - switch (trigger.getType()) { - case AUTO: - return buildAutoTrigger(); - case TIME: - return buildTimeTrigger(trigger); - case USER: - return buildUserTrigger(); - default: - throw new IllegalArgumentException(trigger.getType() + " is not a valid Trigger type"); - } - } - - private AutoTrigger buildAutoTrigger() { - return new AutoTrigger(); - } - - private TimeTrigger buildTimeTrigger(com.netgrif.application.engine.importer.model.Trigger trigger) throws DateTimeParseException { - if (trigger.getDelay() != null) { - return new DelayTimeTrigger(trigger.getDelay().toString()); - } else if (trigger.getExact() != null) { - return new DateTimeTrigger(trigger.getExact().toString()); - } - throw new IllegalArgumentException("Unsupported time trigger value"); - } - - private UserTrigger buildUserTrigger() { - return new UserTrigger(); - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/BooleanFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/BooleanFieldBuilder.java index 23bb59aa24a..cf7199a70b8 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/BooleanFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/BooleanFieldBuilder.java @@ -4,10 +4,12 @@ import com.netgrif.application.engine.importer.model.DataType; import com.netgrif.application.engine.importer.service.Importer; import com.netgrif.application.engine.petrinet.domain.dataset.BooleanField; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; import com.netgrif.application.engine.workflow.domain.DataFieldBehaviors; import org.bson.types.ObjectId; import org.springframework.stereotype.Component; +import java.time.LocalDate; import java.util.HashMap; @Component @@ -17,11 +19,7 @@ public class BooleanFieldBuilder extends FieldBuilder<BooleanField> { public BooleanField build(Data data, Importer importer) { BooleanField field = new BooleanField(); initialize(field); - setDefaultValue(field, data, defaultValue -> { - if (defaultValue != null) { - field.setDefaultValue(Boolean.valueOf(defaultValue)); - } - }); + setDefaultValue(field, data, Boolean::parseBoolean); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/ButtonFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/ButtonFieldBuilder.java index 504d3a431e2..6bb4da14c7d 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/ButtonFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/ButtonFieldBuilder.java @@ -13,11 +13,7 @@ public class ButtonFieldBuilder extends FieldBuilder<ButtonField> { public ButtonField build(Data data, Importer importer) { ButtonField field = new ButtonField(); initialize(field); - setDefaultValue(field, data, defaultValue -> { - if (defaultValue != null) { - field.setDefaultValue(Integer.parseInt(defaultValue)); - } - }); + setDefaultValue(field, data, Integer::parseInt); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/CaseRefFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/CaseRefFieldBuilder.java index 15e7cfdb743..a4cb68262f9 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/CaseRefFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/CaseRefFieldBuilder.java @@ -1,27 +1,22 @@ package com.netgrif.application.engine.importer.service.builder; -import com.netgrif.application.engine.importer.model.AllowedNets; import com.netgrif.application.engine.importer.model.Data; import com.netgrif.application.engine.importer.model.DataType; import com.netgrif.application.engine.importer.service.Importer; import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; import org.springframework.stereotype.Component; -import java.util.ArrayList; +import java.util.List; @Component -public class CaseRefFieldBuilder extends FieldBuilder<CaseField> { +public class CaseRefFieldBuilder extends FieldWithAllowedNetsBuilder<CaseField, List<String>> { @Override public CaseField build(Data data, Importer importer) { - AllowedNets nets = data.getAllowedNets(); CaseField field = new CaseField(); initialize(field); - if (nets != null) { - field.setAllowedNets(new ArrayList<>(nets.getAllowedNet())); - } - setDefaultValues(field, data, ignored -> { - }); + setAllowedNets(field, data); + setDefaultValue(field, data); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/ChoiceFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/ChoiceFieldBuilder.java new file mode 100644 index 00000000000..371816c0d47 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/ChoiceFieldBuilder.java @@ -0,0 +1,43 @@ +package com.netgrif.application.engine.importer.service.builder; + +import com.netgrif.application.engine.importer.model.Data; +import com.netgrif.application.engine.importer.model.Init; +import com.netgrif.application.engine.importer.model.Option; +import com.netgrif.application.engine.importer.service.Importer; +import com.netgrif.application.engine.petrinet.domain.I18nString; +import com.netgrif.application.engine.petrinet.domain.dataset.ChoiceField; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.stream.Collectors; + +public abstract class ChoiceFieldBuilder<T extends ChoiceField<U>, U> extends FieldBuilder<T> { + + public void setFieldOptions(ChoiceField<?> field, Data data, Importer importer) { + if (data.getOptions() == null) { + return; + } + Init initExpression = data.getOptions().getInit(); + if (initExpression != null) { + setDynamicOptions(field, initExpression); + } else { + setStaticOptions(field, data, importer); + } + } + + private void setStaticOptions(ChoiceField<?> field, Data data, Importer importer) { + List<Option> option = data.getOptions().getOption(); + if (option == null || option.isEmpty()) { + return; + } + LinkedHashSet<I18nString> options = option.stream() + .map(importer::toI18NString) + .collect(Collectors.toCollection(LinkedHashSet::new)); + field.setChoices(options); + } + + private void setDynamicOptions(ChoiceField<?> field, Init initExpression) { + field.setExpression(Expression.ofDynamic(initExpression.getValue())); + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/DateFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/DateFieldBuilder.java index 97fc4a2fad3..13d577f092a 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/DateFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/DateFieldBuilder.java @@ -8,6 +8,8 @@ import org.springframework.stereotype.Component; import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; import java.util.Optional; @Component @@ -17,13 +19,8 @@ public class DateFieldBuilder extends FieldBuilder<DateField> { public DateField build(Data data, Importer importer) { DateField field = new DateField(); initialize(field); - setDefaultValue(field, data, defaultValueString -> { - if (defaultValueString == null) { - return; - } - Optional<LocalDate> defaultValue = DateUtils.parseDate(defaultValueString); - field.setDefaultValue(defaultValue.orElse(null)); - }); + // TODO: release/8.0.0 + setDefaultValue(field, data,s -> LocalDate.parse(s, DateTimeFormatter.ISO_LOCAL_DATE)); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/DateTimeFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/DateTimeFieldBuilder.java index a0c16dc3f68..0ebde4b868e 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/DateTimeFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/DateTimeFieldBuilder.java @@ -19,12 +19,9 @@ public class DateTimeFieldBuilder extends FieldBuilder<DateTimeField> { public DateTimeField build(Data data, Importer importer) { DateTimeField field = new DateTimeField(); initialize(field); - setDefaultValue(field, data, defaultValueString -> { - if (defaultValueString == null) { - return; - } - Optional<LocalDateTime> defaultValue = DateUtils.parseDateTime(defaultValueString); - field.setDefaultValue(defaultValue.orElse(null)); + setDefaultValue(field, data, s -> { + Optional<LocalDateTime> localDateTime = DateUtils.parseDateTime(s); + return localDateTime.orElse(null); }); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/EnumerationFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/EnumerationFieldBuilder.java index af77eda342a..c038e4ba12f 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/EnumerationFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/EnumerationFieldBuilder.java @@ -8,7 +8,7 @@ import org.springframework.stereotype.Component; @Component -public class EnumerationFieldBuilder extends FieldBuilder<EnumerationField> { +public class EnumerationFieldBuilder extends ChoiceFieldBuilder<EnumerationField, I18nString> { @Override public EnumerationField build(Data data, Importer importer) { @@ -16,15 +16,8 @@ public EnumerationField build(Data data, Importer importer) { initialize(field); if (data.getOptions() != null) { setFieldOptions(field, data, importer); - } else { - setFieldChoices(field, data, importer); } - // TODO: release/8.0.0 double check with NAE-1757 in 6.3.0 and write test, multichoiceFieldBuilder too - setDefaultValue(field, data, init -> { - if (init != null && !init.equals("")) { - field.setDefaultValue(new I18nString(init)); - } - }); + setDefaultValue(field, data, I18nString::new); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/EnumerationMapFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/EnumerationMapFieldBuilder.java index adfda215d3d..1615d3fbe85 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/EnumerationMapFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/EnumerationMapFieldBuilder.java @@ -3,22 +3,21 @@ import com.netgrif.application.engine.importer.model.Data; import com.netgrif.application.engine.importer.model.DataType; import com.netgrif.application.engine.importer.service.Importer; +import com.netgrif.application.engine.petrinet.domain.I18nString; import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField; import org.springframework.stereotype.Component; +import java.util.function.Function; + @Component -public class EnumerationMapFieldBuilder extends FieldBuilder<EnumerationMapField> { +public class EnumerationMapFieldBuilder extends MapOptionsFieldBuilder<EnumerationMapField, String> { @Override public EnumerationMapField build(Data data, Importer importer) { EnumerationMapField field = new EnumerationMapField(); initialize(field); setFieldOptions(field, data, importer); - setDefaultValue(field, data, init -> { - if (init != null && !init.isEmpty()) { - field.setDefaultValue(init); - } - }); + setDefaultValue(field, data, Function.identity()); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/FieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/FieldBuilder.java index 2ce23ecc26e..2162a2e727c 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/FieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/FieldBuilder.java @@ -2,20 +2,16 @@ import com.netgrif.application.engine.importer.model.Data; import com.netgrif.application.engine.importer.model.DataType; -import com.netgrif.application.engine.importer.model.Init; -import com.netgrif.application.engine.importer.model.Option; import com.netgrif.application.engine.importer.service.Importer; -import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.petrinet.domain.dataset.ChoiceField; import com.netgrif.application.engine.petrinet.domain.dataset.Field; -import com.netgrif.application.engine.petrinet.domain.dataset.MapOptionsField; import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; +import com.netgrif.application.engine.utils.UniqueKeyMapWrapper; import com.netgrif.application.engine.workflow.domain.DataFieldBehaviors; import org.bson.types.ObjectId; -import java.util.*; -import java.util.function.Consumer; -import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.function.Function; public abstract class FieldBuilder<T extends Field<?>> { @@ -28,6 +24,25 @@ public void initialize(Field<?> field) { field.setEvents(new HashMap<>()); field.setBehaviors(new DataFieldBehaviors()); field.setValidations(new ArrayList<>()); + field.setProperties(new UniqueKeyMapWrapper<>()); + } + + public <U> void setDefaultValue(Field<U> field, Data data) { + setDefaultValue(field, data, null); + } + + public <U> void setDefaultValue(Field<U> field, Data data, Function<String, U> staticValue) { + String definition = getInitExpression(data); + Expression<U> initExpression = null; + if (definition != null) { + initExpression = Expression.ofDynamic(definition); + } else { + String init = resolveInit(data); + if (init != null && staticValue != null) { + initExpression = Expression.ofStatic(staticValue.apply(init)); + } + } + field.setDefaultValue(initExpression); } public String getInitExpression(Data data) { @@ -40,72 +55,9 @@ public String getInitExpression(Data data) { } public String resolveInit(Data data) { - if (data.getInits() != null && data.getInits().getInit() != null) { - return data.getInits().getInit().get(0).getValue(); - } - if (data.getInit() != null) return data.getInit().getValue(); - return null; - } - - public List<String> resolveInits(Data data) { - if (data.getInits() != null && data.getInits().getInit() != null) { - return data.getInits().getInit().stream().map(Init::getValue).collect(Collectors.toList()); - } - if (data.getInit() != null) { - return List.of(data.getInit().getValue().trim().split("\\s*,\\s*")); - } - return Collections.emptyList(); - } - - public void setFieldChoices(ChoiceField<?> field, Data data, Importer importer) { - if (data.getValues() != null && !data.getValues().isEmpty() && data.getValues().get(0).isDynamic()) { - field.setExpression(new Expression(data.getValues().get(0).getValue(), data.getValues().get(0).isDynamic())); - } else if (data.getValues() != null) { - List<I18nString> choices = data.getValues().stream() - .map(importer::toI18NString) - .collect(Collectors.toList()); - field.getChoices().addAll(choices); - } - } - - public void setFieldOptions(ChoiceField<?> field, Data data, Importer importer) { - if (data.getOptions() != null && data.getOptions().getInit() != null) { - field.setExpression(new Expression(data.getOptions().getInit().getValue(), data.getOptions().getInit().isDynamic())); - return; - } - - List<I18nString> options = (data.getOptions() == null) ? new ArrayList<>() : data.getOptions().getOption().stream() - .map(importer::toI18NString) - .collect(Collectors.toList()); - field.getChoices().addAll(options); - } - - public void setFieldOptions(MapOptionsField<I18nString, ?> field, Data data, Importer importer) { - if (data.getOptions() != null && data.getOptions().getInit() != null) { - field.setExpression(new Expression(data.getOptions().getInit().getValue(), data.getOptions().getInit().isDynamic())); - return; - } - - Map<String, I18nString> choices = (data.getOptions() == null) ? new LinkedHashMap<>() : data.getOptions().getOption().stream() - .collect(Collectors.toMap(Option::getKey, importer::toI18NString, (o1, o2) -> o1, LinkedHashMap::new)); - field.setOptions(choices); - } - - public void setDefaultValue(Field<?> field, Data data, Consumer<String> setDefault) { - String initExpression = getInitExpression(data); - if (initExpression != null) { - field.setInitExpression(new Expression(initExpression, true)); - } else { - setDefault.accept(resolveInit(data)); - } - } - - public void setDefaultValues(Field<?> field, Data data, Consumer<List<String>> setDefault) { - String initExpression = getInitExpression(data); - if (initExpression != null) { - field.setInitExpression(new Expression(initExpression, true)); - } else { - setDefault.accept(resolveInits(data)); + if (data.getInit() == null) { + return null; } + return data.getInit().getValue(); } } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/FieldWithAllowedNetsBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/FieldWithAllowedNetsBuilder.java new file mode 100644 index 00000000000..8f348f8c4f7 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/FieldWithAllowedNetsBuilder.java @@ -0,0 +1,18 @@ +package com.netgrif.application.engine.importer.service.builder; + +import com.netgrif.application.engine.importer.model.AllowedNets; +import com.netgrif.application.engine.importer.model.Data; +import com.netgrif.application.engine.petrinet.domain.dataset.FieldWithAllowedNets; + +import java.util.ArrayList; + +public abstract class FieldWithAllowedNetsBuilder<T extends FieldWithAllowedNets<U>, U> extends FieldBuilder<T> { + + public void setAllowedNets(T field, Data data) { + AllowedNets nets = data.getAllowedNets(); + if (nets == null || nets.getAllowedNet() == null || nets.getAllowedNet().isEmpty()) { + return; + } + field.setAllowedNets(new ArrayList<>(nets.getAllowedNet())); + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/FieldWithAllowedRolesBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/FieldWithAllowedRolesBuilder.java new file mode 100644 index 00000000000..0bbc29dccf7 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/FieldWithAllowedRolesBuilder.java @@ -0,0 +1,22 @@ +package com.netgrif.application.engine.importer.service.builder; + +import com.netgrif.application.engine.importer.model.Data; +import com.netgrif.application.engine.importer.model.Option; +import com.netgrif.application.engine.importer.model.Options; +import com.netgrif.application.engine.petrinet.domain.dataset.FieldWithAllowedRoles; + +import java.util.Set; +import java.util.stream.Collectors; + +public abstract class FieldWithAllowedRolesBuilder<T extends FieldWithAllowedRoles<U>, U> extends FieldBuilder<T> { + + public void setRoles(T field, Data data) { + Options options = data.getOptions(); + if (options == null || options.getOption() == null || options.getOption().isEmpty()) { + return; + } + Set<String> roles = options.getOption().stream() + .map(Option::getValue).collect(Collectors.toSet()); + field.setAllowedRoleImportIds(roles); + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/FileFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/FileFieldBuilder.java index 1735e4a4f8c..04c21a790b9 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/FileFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/FileFieldBuilder.java @@ -13,12 +13,7 @@ public class FileFieldBuilder extends FieldBuilder<FileField> { public FileField build(Data data, Importer importer) { FileField field = new FileField(); initialize(field); - field.setRemote(data.getRemote() != null); - setDefaultValue(field, data, defaultValue -> { - if (defaultValue != null) { - field.setDefaultValue(defaultValue); - } - }); + setDefaultValue(field, data); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/FileListFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/FileListFieldBuilder.java index 716e374f0c7..f7974783153 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/FileListFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/FileListFieldBuilder.java @@ -13,12 +13,7 @@ public class FileListFieldBuilder extends FieldBuilder<FileListField> { public FileListField build(Data data, Importer importer) { FileListField field = new FileListField(); initialize(field); - field.setRemote(data.getRemote() != null); - setDefaultValues(field, data, defaultValues -> { - if (defaultValues != null && !defaultValues.isEmpty()) { - field.setDefaultValue(defaultValues); - } - }); + setDefaultValue(field, data); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/FilterFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/FilterFieldBuilder.java index e437a34a65d..24b9daa65e2 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/FilterFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/FilterFieldBuilder.java @@ -1,27 +1,20 @@ package com.netgrif.application.engine.importer.service.builder; -import com.netgrif.application.engine.importer.model.AllowedNets; import com.netgrif.application.engine.importer.model.Data; import com.netgrif.application.engine.importer.model.DataType; import com.netgrif.application.engine.importer.service.Importer; import com.netgrif.application.engine.petrinet.domain.dataset.FilterField; import org.springframework.stereotype.Component; -import java.util.ArrayList; - @Component -public class FilterFieldBuilder extends FieldBuilder<FilterField> { +public class FilterFieldBuilder extends FieldWithAllowedNetsBuilder<FilterField, String> { @Override public FilterField build(Data data, Importer importer) { - AllowedNets nets = data.getAllowedNets(); FilterField field = new FilterField(); initialize(field); - if (nets != null) { - field.setAllowedNets(new ArrayList<>(nets.getAllowedNet())); - } - // TODO: release/8.0.0 setDefaultValue? - setDefaultValue(field, data, ignored -> {}); + setAllowedNets(field, data); + setDefaultValue(field, data); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/I18nFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/I18nFieldBuilder.java index c83ef1d5338..f3266d37c8b 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/I18nFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/I18nFieldBuilder.java @@ -15,21 +15,7 @@ public class I18nFieldBuilder extends FieldBuilder<I18nField> { public I18nField build(Data data, Importer importer) { I18nField field = new I18nField(); initialize(field); - String initExpression = getInitExpression(data); - if (initExpression != null) { - field.setInitExpression(new Expression(initExpression, true)); - } else { - // TODO: release/8.0.0 simplify - if (data.getInits() != null && data.getInits().getInit() != null && !data.getInits().getInit().isEmpty()) { - field.setDefaultValue(new I18nString(data.getInits().getInit().get(0).getValue())); - } else if (data.getInit() != null && (data.getInit().getName() == null || data.getInit().getName().equals(""))) { - field.setDefaultValue(new I18nString(data.getInit().getValue())); - } else if (data.getInit() != null && data.getInit().getName() != null && !data.getInit().getName().equals("")) { - field.setDefaultValue(importer.toI18NString(data.getInit())); - } else { - field.setDefaultValue(new I18nString("")); - } - } + setDefaultValue(field, data, I18nString::new); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/MapOptionsFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/MapOptionsFieldBuilder.java new file mode 100644 index 00000000000..0ec4327fc01 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/MapOptionsFieldBuilder.java @@ -0,0 +1,42 @@ +package com.netgrif.application.engine.importer.service.builder; + +import com.netgrif.application.engine.importer.model.Data; +import com.netgrif.application.engine.importer.model.Init; +import com.netgrif.application.engine.importer.model.Option; +import com.netgrif.application.engine.importer.service.Importer; +import com.netgrif.application.engine.petrinet.domain.I18nString; +import com.netgrif.application.engine.petrinet.domain.dataset.MapOptionsField; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.stream.Collectors; + +public abstract class MapOptionsFieldBuilder<T extends MapOptionsField<I18nString, V>, V> extends FieldBuilder<T> { + + public void setFieldOptions(MapOptionsField<I18nString, V> field, Data data, Importer importer) { + if (data.getOptions() == null) { + return; + } + Init initExpression = data.getOptions().getInit(); + if (initExpression != null) { + setDynamicOptions(field, initExpression); + } else { + setStaticOptions(field, data, importer); + } + } + + private void setStaticOptions(MapOptionsField<I18nString, V> field, Data data, Importer importer) { + List<Option> option = data.getOptions().getOption(); + if (option == null || option.isEmpty()) { + return; + } + LinkedHashMap<String, I18nString> options = option.stream() + .collect(Collectors.toMap(Option::getKey, importer::toI18NString, (o1, o2) -> o1, LinkedHashMap::new)); + field.setOptions(options); + } + + private void setDynamicOptions(MapOptionsField<I18nString, V> field, Init initExpression) { + field.setOptionsExpression(Expression.ofDynamic(initExpression.getValue())); + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/MultichoiceFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/MultichoiceFieldBuilder.java index a068e4096ab..4da7489410c 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/MultichoiceFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/MultichoiceFieldBuilder.java @@ -7,10 +7,10 @@ import com.netgrif.application.engine.petrinet.domain.dataset.MultichoiceField; import org.springframework.stereotype.Component; -import java.util.stream.Collectors; +import java.util.LinkedHashSet; @Component -public class MultichoiceFieldBuilder extends FieldBuilder<MultichoiceField> { +public class MultichoiceFieldBuilder extends ChoiceFieldBuilder<MultichoiceField, LinkedHashSet<I18nString>> { @Override public MultichoiceField build(Data data, Importer importer) { @@ -18,13 +18,12 @@ public MultichoiceField build(Data data, Importer importer) { initialize(field); if (data.getOptions() != null) { setFieldOptions(field, data, importer); - } else { - setFieldChoices(field, data, importer); } - setDefaultValues(field, data, init -> { - if (init != null && !init.isEmpty()) { - field.setDefaultValue(init.stream().map(I18nString::new).collect(Collectors.toSet())); - } + setDefaultValue(field, data, s -> { + // todo: release/8.0.0 data.init string split by comma and iterate + LinkedHashSet<I18nString> value = new LinkedHashSet<>(); + value.add(new I18nString(s)); + return value; }); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/MultichoiceMapFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/MultichoiceMapFieldBuilder.java index e79656e7a61..1e205a1765f 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/MultichoiceMapFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/MultichoiceMapFieldBuilder.java @@ -6,24 +6,17 @@ import com.netgrif.application.engine.petrinet.domain.dataset.MultichoiceMapField; import org.springframework.stereotype.Component; -import java.util.HashSet; import java.util.Set; @Component -public class MultichoiceMapFieldBuilder extends FieldBuilder<MultichoiceMapField> { +public class MultichoiceMapFieldBuilder extends MapOptionsFieldBuilder<MultichoiceMapField, Set<String>> { @Override public MultichoiceMapField build(Data data, Importer importer) { MultichoiceMapField field = new MultichoiceMapField(); initialize(field); setFieldOptions(field, data, importer); - setDefaultValues(field, data, init -> { - Set<String> defaultValue = new HashSet<>(); - if (init != null && !init.isEmpty()) { - defaultValue.addAll(init); - } - field.setDefaultValue(defaultValue); - }); + setDefaultValue(field, data, Set::of); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/NumberFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/NumberFieldBuilder.java index b313e6cc0f5..d48a1e18041 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/NumberFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/NumberFieldBuilder.java @@ -13,11 +13,7 @@ public class NumberFieldBuilder extends FieldBuilder<NumberField> { public NumberField build(Data data, Importer importer) { NumberField field = new NumberField(); initialize(field); - setDefaultValue(field, data, defaultValue -> { - if (defaultValue != null) { - field.setDefaultValue(Double.parseDouble(defaultValue)); - } - }); + setDefaultValue(field, data, Double::parseDouble); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/StringCollectionFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/StringCollectionFieldBuilder.java new file mode 100644 index 00000000000..6ba5ac8ea86 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/StringCollectionFieldBuilder.java @@ -0,0 +1,25 @@ +package com.netgrif.application.engine.importer.service.builder; + +import com.netgrif.application.engine.importer.model.Data; +import com.netgrif.application.engine.importer.model.DataType; +import com.netgrif.application.engine.importer.service.Importer; +import com.netgrif.application.engine.petrinet.domain.dataset.StringCollectionField; +import org.springframework.stereotype.Component; + +@Component +public class StringCollectionFieldBuilder extends FieldBuilder<StringCollectionField> { + + @Override + public StringCollectionField build(Data data, Importer importer) { + StringCollectionField field = new StringCollectionField(); + initialize(field); + // TODO: release/8.0.0 + setDefaultValue(field, data); + return field; + } + + @Override + public DataType getType() { + return DataType.STRING_COLLECTION; + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/TaskRefFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/TaskRefFieldBuilder.java index d2f09a7c593..d838153cbd9 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/TaskRefFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/TaskRefFieldBuilder.java @@ -18,17 +18,7 @@ public class TaskRefFieldBuilder extends FieldBuilder<TaskField> { public TaskField build(Data data, Importer importer) { TaskField field = new TaskField(); initialize(field); - setDefaultValues(field, data, defaultValues -> { - if (defaultValues != null && !defaultValues.isEmpty()) { - List<String> defaults = new ArrayList<>(); - defaultValues.forEach(s -> { - if (importer.getDocument().getTransition().stream().noneMatch(t -> t.getId().equals(s))) - log.warn("There is no transition with id [" + s + "]"); - defaults.add(s); - }); - field.setDefaultValue(defaults); - } - }); + setDefaultValue(field, data, List::of); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/TextFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/TextFieldBuilder.java index 48fd3ccf008..0127c860ba5 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/TextFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/TextFieldBuilder.java @@ -2,13 +2,10 @@ import com.netgrif.application.engine.importer.model.Data; import com.netgrif.application.engine.importer.model.DataType; -import com.netgrif.application.engine.importer.model.I18NStringTypeWithExpression; import com.netgrif.application.engine.importer.service.Importer; import com.netgrif.application.engine.petrinet.domain.dataset.TextField; import org.springframework.stereotype.Component; -import java.util.List; - @Component public class TextFieldBuilder extends FieldBuilder<TextField> { @@ -16,13 +13,7 @@ public class TextFieldBuilder extends FieldBuilder<TextField> { public TextField build(Data data, Importer importer) { TextField field = new TextField(); initialize(field); - String value = null; - List<I18NStringTypeWithExpression> values = data.getValues(); - if (values != null && !values.isEmpty()) { - value = values.get(0).getValue(); - } - field.setRawValue(value); // TODO: release/8.0.0 is it necessary? - setDefaultValue(field, data, field::setDefaultValue); + setDefaultValue(field, data, s -> s); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/UserFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/UserFieldBuilder.java index 6e444f8e883..cf09dc98c11 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/UserFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/UserFieldBuilder.java @@ -2,34 +2,20 @@ import com.netgrif.application.engine.importer.model.Data; import com.netgrif.application.engine.importer.model.DataType; -import com.netgrif.application.engine.importer.model.Option; import com.netgrif.application.engine.importer.service.Importer; import com.netgrif.application.engine.petrinet.domain.dataset.UserField; +import com.netgrif.application.engine.petrinet.domain.dataset.UserFieldValue; import org.springframework.stereotype.Component; -import java.util.Set; -import java.util.stream.Collectors; - @Component -public class UserFieldBuilder extends FieldBuilder<UserField> { +public class UserFieldBuilder extends FieldWithAllowedRolesBuilder<UserField, UserFieldValue> { @Override public UserField build(Data data, Importer importer) { UserField field = new UserField(); initialize(field); - if (data.getOptions() != null && data.getOptions().getOption() != null) { - Set<String> roles = data.getOptions().getOption().stream() - .map(Option::getKey) - .collect(Collectors.toSet()); - field.setRoles(roles); - } else if (data.getValues() != null) { - Set<String> roles = data.getValues().stream() - .map(value -> importer.getRoles().get(value.getValue()).getStringId()) - .collect(Collectors.toSet()); - field.setRoles(roles); - } - // TODO:release/8.0.0 user datafield had roles as choices in 6.x - setDefaultValue(field, data, inits -> field.setDefaultValue(null)); + setRoles(field, data); + setDefaultValue(field, data); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/builder/UserListFieldBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/builder/UserListFieldBuilder.java index 0ff4c97fd5a..ca787038c39 100644 --- a/src/main/java/com/netgrif/application/engine/importer/service/builder/UserListFieldBuilder.java +++ b/src/main/java/com/netgrif/application/engine/importer/service/builder/UserListFieldBuilder.java @@ -4,19 +4,18 @@ import com.netgrif.application.engine.importer.model.DataType; import com.netgrif.application.engine.importer.service.Importer; import com.netgrif.application.engine.petrinet.domain.dataset.UserListField; -import lombok.extern.slf4j.Slf4j; +import com.netgrif.application.engine.petrinet.domain.dataset.UserListFieldValue; import org.springframework.stereotype.Component; @Component -public class UserListFieldBuilder extends FieldBuilder<UserListField> { +public class UserListFieldBuilder extends FieldWithAllowedRolesBuilder<UserListField, UserListFieldValue> { @Override public UserListField build(Data data, Importer importer) { UserListField field = new UserListField(); initialize(field); - setDefaultValues(field, data, inits -> { -// TODO: release/8.0.0 - }); + setRoles(field, data); + setDefaultValue(field, data); return field; } diff --git a/src/main/java/com/netgrif/application/engine/importer/service/evaluation/ActionEvaluator.java b/src/main/java/com/netgrif/application/engine/importer/service/evaluation/ActionEvaluator.java new file mode 100644 index 00000000000..6fe0a6d6c7d --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/evaluation/ActionEvaluator.java @@ -0,0 +1,31 @@ +package com.netgrif.application.engine.importer.service.evaluation; + +import com.netgrif.application.engine.petrinet.domain.Function; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionRunner; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@ConditionalOnProperty(prefix = "nae.importer", name = "evaluate-actions", havingValue = "true", matchIfMissing = true) +public class ActionEvaluator implements IActionEvaluator { + + private final ActionRunner actionRunner; + + public ActionEvaluator(ActionRunner actionRunner) { + this.actionRunner = actionRunner; + } + + @Override + public void evaluate(List<Action> actions, List<Function> functions) { + actions.forEach(action -> { + try { + actionRunner.getActionCode(action, functions, null, true); + } catch (Exception e) { + throw new IllegalArgumentException("Could not evaluate action[" + action.getImportId() + "]: \n " + action.getDefinition(), e); + } + }); + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/evaluation/FunctionEvaluator.java b/src/main/java/com/netgrif/application/engine/importer/service/evaluation/FunctionEvaluator.java new file mode 100644 index 00000000000..2888a4f6760 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/evaluation/FunctionEvaluator.java @@ -0,0 +1,30 @@ +package com.netgrif.application.engine.importer.service.evaluation; + +import com.netgrif.application.engine.petrinet.domain.Function; +import com.netgrif.application.engine.workflow.service.interfaces.IFieldActionsCacheService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Slf4j +@Service +@ConditionalOnProperty(prefix = "nae.importer", value = "evaluate-functions", havingValue = "true", matchIfMissing = true) +public class FunctionEvaluator implements IFunctionEvaluator { + + protected final IFieldActionsCacheService actionsCacheService; + + public FunctionEvaluator(IFieldActionsCacheService actionsCacheService) { + this.actionsCacheService = actionsCacheService; + } + + @Override + public void evaluate(List<Function> functions) { + try { + actionsCacheService.evaluateFunctions(functions); + } catch (Exception e) { + throw new IllegalArgumentException("Could not evaluate functions: " + e.getMessage(), e); + } + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/evaluation/IActionEvaluator.java b/src/main/java/com/netgrif/application/engine/importer/service/evaluation/IActionEvaluator.java new file mode 100644 index 00000000000..965673a066d --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/evaluation/IActionEvaluator.java @@ -0,0 +1,11 @@ +package com.netgrif.application.engine.importer.service.evaluation; + +import com.netgrif.application.engine.petrinet.domain.Function; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; + +import java.util.List; + +public interface IActionEvaluator { + + void evaluate(List<Action> actions, List<Function> functions); +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/evaluation/IFunctionEvaluator.java b/src/main/java/com/netgrif/application/engine/importer/service/evaluation/IFunctionEvaluator.java new file mode 100644 index 00000000000..af1a76e93ca --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/evaluation/IFunctionEvaluator.java @@ -0,0 +1,10 @@ +package com.netgrif.application.engine.importer.service.evaluation; + +import com.netgrif.application.engine.petrinet.domain.Function; + +import java.util.List; + +public interface IFunctionEvaluator { + + void evaluate(List<Function> functions); +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/evaluation/SkipActionEvaluator.java b/src/main/java/com/netgrif/application/engine/importer/service/evaluation/SkipActionEvaluator.java new file mode 100644 index 00000000000..cd36bec2498 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/evaluation/SkipActionEvaluator.java @@ -0,0 +1,20 @@ +package com.netgrif.application.engine.importer.service.evaluation; + +import com.netgrif.application.engine.petrinet.domain.Function; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Slf4j +@Service +@ConditionalOnProperty(prefix = "nae.importer", name = "evaluate-actions", havingValue = "false") +public class SkipActionEvaluator implements IActionEvaluator { + + @Override + public void evaluate(List<Action> actions, List<Function> functions) { + log.info("Skipping evaluation of actions"); + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/evaluation/SkipFunctionEvaluator.java b/src/main/java/com/netgrif/application/engine/importer/service/evaluation/SkipFunctionEvaluator.java new file mode 100644 index 00000000000..dde079f7f30 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/evaluation/SkipFunctionEvaluator.java @@ -0,0 +1,18 @@ +package com.netgrif.application.engine.importer.service.evaluation; + +import com.netgrif.application.engine.petrinet.domain.Function; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Slf4j +@Service +@ConditionalOnProperty(prefix = "nae.importer", value = "evaluate-functions", havingValue = "false") +public class SkipFunctionEvaluator implements IFunctionEvaluator { + @Override + public void evaluate(List<Function> functions) { + log.info("Skipping evaluation of functions"); + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/trigger/AutoTriggerBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/trigger/AutoTriggerBuilder.java new file mode 100644 index 00000000000..a6d8d012b6a --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/trigger/AutoTriggerBuilder.java @@ -0,0 +1,20 @@ +package com.netgrif.application.engine.importer.service.trigger; + +import com.netgrif.application.engine.importer.model.TriggerType; +import com.netgrif.application.engine.workflow.domain.triggers.AutoTrigger; +import com.netgrif.application.engine.workflow.domain.triggers.Trigger; +import org.springframework.stereotype.Component; + +@Component +public class AutoTriggerBuilder extends TriggerBuilder { + + @Override + public Trigger build(com.netgrif.application.engine.importer.model.Trigger trigger) { + return new AutoTrigger(); + } + + @Override + public TriggerType getType() { + return TriggerType.AUTO; + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/trigger/TimeTriggerBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/trigger/TimeTriggerBuilder.java new file mode 100644 index 00000000000..0006041753b --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/trigger/TimeTriggerBuilder.java @@ -0,0 +1,26 @@ +package com.netgrif.application.engine.importer.service.trigger; + +import com.netgrif.application.engine.importer.model.TriggerType; +import com.netgrif.application.engine.workflow.domain.triggers.DateTimeTrigger; +import com.netgrif.application.engine.workflow.domain.triggers.DelayTimeTrigger; +import com.netgrif.application.engine.workflow.domain.triggers.Trigger; +import org.springframework.stereotype.Component; + +@Component +public class TimeTriggerBuilder extends TriggerBuilder { + + @Override + public Trigger build(com.netgrif.application.engine.importer.model.Trigger trigger) { + if (trigger.getDelay() != null) { + return new DelayTimeTrigger(trigger.getDelay().toString()); + } else if (trigger.getExact() != null) { + return new DateTimeTrigger(trigger.getExact().toString()); + } + throw new IllegalArgumentException("Unsupported time trigger value"); + } + + @Override + public TriggerType getType() { + return TriggerType.TIME; + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/trigger/TriggerBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/trigger/TriggerBuilder.java new file mode 100644 index 00000000000..e4987256226 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/trigger/TriggerBuilder.java @@ -0,0 +1,11 @@ +package com.netgrif.application.engine.importer.service.trigger; + +import com.netgrif.application.engine.importer.model.TriggerType; +import com.netgrif.application.engine.workflow.domain.triggers.Trigger; + +public abstract class TriggerBuilder { + + public abstract Trigger build(com.netgrif.application.engine.importer.model.Trigger trigger); + + public abstract TriggerType getType(); +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/trigger/TriggerFactory.java b/src/main/java/com/netgrif/application/engine/importer/service/trigger/TriggerFactory.java new file mode 100644 index 00000000000..9bebc29f21a --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/trigger/TriggerFactory.java @@ -0,0 +1,31 @@ +package com.netgrif.application.engine.importer.service.trigger; + +import com.netgrif.application.engine.importer.model.TriggerType; +import com.netgrif.application.engine.workflow.domain.triggers.Trigger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.format.DateTimeParseException; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Component +public class TriggerFactory { + + private final Map<TriggerType, TriggerBuilder> builders; + + @Autowired + public TriggerFactory(List<TriggerBuilder> builders) { + this.builders = builders.stream().collect(Collectors.toMap(TriggerBuilder::getType, Function.identity())); + } + + public Trigger buildTrigger(com.netgrif.application.engine.importer.model.Trigger trigger) throws IllegalArgumentException, DateTimeParseException { + TriggerBuilder builder = builders.get(trigger.getType()); + if (builder == null) { + throw new IllegalArgumentException(trigger.getType() + " is not a valid Trigger type"); + } + return builder.build(trigger); + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/importer/service/trigger/UserTriggerBuilder.java b/src/main/java/com/netgrif/application/engine/importer/service/trigger/UserTriggerBuilder.java new file mode 100644 index 00000000000..963ed969c3c --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/trigger/UserTriggerBuilder.java @@ -0,0 +1,20 @@ +package com.netgrif.application.engine.importer.service.trigger; + +import com.netgrif.application.engine.importer.model.TriggerType; +import com.netgrif.application.engine.workflow.domain.triggers.Trigger; +import com.netgrif.application.engine.workflow.domain.triggers.ActorTrigger; +import org.springframework.stereotype.Component; + +@Component +public class UserTriggerBuilder extends TriggerBuilder { + + @Override + public Trigger build(com.netgrif.application.engine.importer.model.Trigger trigger) { + return new ActorTrigger(); + } + + @Override + public TriggerType getType() { + return TriggerType.ACTOR; + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/ActionValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/ActionValidator.java deleted file mode 100644 index cd6c2fb2d16..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/validation/ActionValidator.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.netgrif.application.engine.importer.service.validation; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Slf4j -@Component -public class ActionValidator extends ModelValidator implements IActionValidator { - - @Override - public void validateAction(String action) { - validateChangeFieldAbout(action); - } - - private void validateChangeFieldAbout(String action) { - if (action.matches("[\\s\\w\\W]*change [\\s\\w\\W]*? about[\\s\\w\\W]*")) { - log.warn("Action [change field about] is deprecated."); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/DataValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/DataValidator.java deleted file mode 100644 index 4cf2a9dfe33..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/validation/DataValidator.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.netgrif.application.engine.importer.service.validation; - -import com.netgrif.application.engine.importer.model.Data; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -public class DataValidator extends ModelValidator implements IDataValidator { - - @Override - public void checkDeprecatedAttributes(Data data) { - validateAttribute(data.getView(), "view", data.getId()); - validateAttribute(data.getValid() != null && !data.getValid().isEmpty() ? data.getValid() : null, "valid", data.getId()); - validateAttribute(data.getFormat(), "format", data.getId()); - validateAttribute(data.getValues() != null && !data.getValues().isEmpty() ? data.getValues() : null, "values", data.getId()); - } - - protected void validateAttribute(Object attr, String attrName, String fieldName) { - if (attr != null) { - log.warn("Data attribute [" + attrName + "] on field [" + fieldName + "] is deprecated."); - } - } -} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/DocumentValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/DocumentValidator.java deleted file mode 100644 index 506bebcbc4f..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/validation/DocumentValidator.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.netgrif.application.engine.importer.service.validation; - -import com.netgrif.application.engine.importer.model.Document; -import com.netgrif.application.engine.importer.service.throwable.BeatingAttributesException; -import org.springframework.stereotype.Component; - -import java.util.Collection; - -@Component -public class DocumentValidator extends ModelValidator implements IDocumentValidator { - - @Override - public void checkDeprecatedAttributes(Document document) { - validateAttribute(document.getUsersRef(), "usersRef"); - } - - @Override - public void checkConflictingAttributes(Document document, Object attr1, Object attr2, String attr1Name, String attr2Name) throws BeatingAttributesException { - if ((attr1 instanceof Collection && attr2 instanceof Collection && !((Collection) attr1).isEmpty() && !((Collection) attr2).isEmpty())) { - throw new BeatingAttributesException("Attributes \"" + attr1Name + "\" and \"" + attr2Name + "\" cannot be present at the same time" + - " on model \"document\" with ID \"" + document.getId() + "\". Consider using only one of them."); - } - if ((!(attr1 instanceof Collection) && !(attr2 instanceof Collection) && attr1 != null && attr2 != null)) { - throw new BeatingAttributesException("Attributes \"" + attr1Name + "\" and \"" + attr2Name + "\" cannot be present at the same time" + - " on model \"document\" with ID \"" + document.getId() + "\". Consider using only one of them."); - } - } -} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/IActionValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/IActionValidator.java deleted file mode 100644 index ca11cbc297f..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/validation/IActionValidator.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.netgrif.application.engine.importer.service.validation; - -public interface IActionValidator extends IModelValidator { - void validateAction(String action); -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/IDataValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/IDataValidator.java deleted file mode 100644 index ceb6b3be3ee..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/validation/IDataValidator.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.netgrif.application.engine.importer.service.validation; - -import com.netgrif.application.engine.importer.model.Data; - -public interface IDataValidator extends IModelValidator { - void checkDeprecatedAttributes(Data data); -} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/IDocumentValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/IDocumentValidator.java deleted file mode 100644 index 87e59b0d4b4..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/validation/IDocumentValidator.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.netgrif.application.engine.importer.service.validation; - -import com.netgrif.application.engine.importer.model.Document; -import com.netgrif.application.engine.importer.service.throwable.BeatingAttributesException; - -public interface IDocumentValidator extends IModelValidator { - void checkDeprecatedAttributes(Document document); - - /** - * Self-beating attributes are two attributes, that should not be present inside their parent at the same time. - * E.g.: if user defines <userRef> in transition, the tag <usersRef> will be disabled, however, additional - * <userRef> tags can be still added. - * - * @param document the model of PetriNet - * @param attr1 first element to be compared - * @param attr2 second element to be compared - * @param attr1Name the name of first element - * @param attr2Name the name of second element - * @throws BeatingAttributesException is thrown when there are two attributes with different type but same goal - */ - void checkConflictingAttributes(Document document, Object attr1, Object attr2, String attr1Name, String attr2Name) throws BeatingAttributesException; -} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/ILogicValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/ILogicValidator.java deleted file mode 100644 index baf6bb75e89..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/validation/ILogicValidator.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.netgrif.application.engine.importer.service.validation; - -import com.netgrif.application.engine.importer.model.Logic; -import com.netgrif.application.engine.importer.service.throwable.BeatingAttributesException; - -public interface ILogicValidator extends IModelValidator { - void checkDeprecatedAttributes(Logic logic); - - /** - * Self-beating attributes are two attributes, that should not be present inside their parent at the same time. - * E.g.: if user defines <userRef> in transition, the tag <usersRef> will be disabled, however, additional - * <userRef> tags can be still added. - * - * @param logic the model of Logic - * @param attr1 first element to be compared - * @param attr2 second element to be compared - * @param attr1Name the name of first element - * @param attr2Name the name of second element - * @throws BeatingAttributesException is thrown when there are two attributes with different type but same goal - */ - void checkConflictingAttributes(Logic logic, Object attr1, Object attr2, String attr1Name, String attr2Name) throws BeatingAttributesException; -} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/IModelValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/IModelValidator.java deleted file mode 100644 index d8e8e6785e7..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/validation/IModelValidator.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.netgrif.application.engine.importer.service.validation; - - -public interface IModelValidator { - void validateAttribute(Object attr, String attrName); -} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/IProcessValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/IProcessValidator.java new file mode 100644 index 00000000000..735bb05b704 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/validation/IProcessValidator.java @@ -0,0 +1,9 @@ +package com.netgrif.application.engine.importer.service.validation; + + +import com.netgrif.application.engine.petrinet.domain.Process; + +public interface IProcessValidator { + + void validate(Process process); +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/ITransitionValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/ITransitionValidator.java deleted file mode 100644 index c38010ade69..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/validation/ITransitionValidator.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.netgrif.application.engine.importer.service.validation; - -import com.netgrif.application.engine.importer.model.Transition; -import com.netgrif.application.engine.importer.service.throwable.BeatingAttributesException; -import com.netgrif.application.engine.importer.service.validation.IModelValidator; - -public interface ITransitionValidator extends IModelValidator { - - void checkDeprecatedAttributes(Transition transition); - - /** - * Self-beating attributes are two attributes, that should not be present inside their parent at the same time. - * E.g.: if user defines <userRef> in transition, the tag <usersRef> will be disabled, however, additional - * <userRef> tags can be still added. - * - * @param transition the model of Transition - * @param attr1 first element to be compared - * @param attr2 second element to be compared - * @param attr1Name the name of first element - * @param attr2Name the name of second element - * @throws BeatingAttributesException is thrown when there are two attributes with different type but same goal - */ - void checkConflictingAttributes(Transition transition, Object attr1, Object attr2, String attr1Name, String attr2Name) throws BeatingAttributesException; -} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/LogicValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/LogicValidator.java deleted file mode 100644 index cea5da90dbd..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/validation/LogicValidator.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.netgrif.application.engine.importer.service.validation; - -import com.netgrif.application.engine.importer.model.Logic; -import com.netgrif.application.engine.importer.service.throwable.BeatingAttributesException; -import org.springframework.stereotype.Component; - -import java.util.Collection; - -@Component -public class LogicValidator extends ModelValidator implements ILogicValidator { - - @Override - public void checkDeprecatedAttributes(Logic logic) { - validateAttribute(logic.isAssigned(), "assigned"); - } - - @Override - public void checkConflictingAttributes(Logic logic, Object attr1, Object attr2, String attr1Name, String attr2Name) throws BeatingAttributesException { - if ((attr1 instanceof Collection && attr2 instanceof Collection && !((Collection) attr1).isEmpty() && !((Collection) attr2).isEmpty())) { - throw new BeatingAttributesException("Attributes \"" + attr1Name + "\" and \"" + attr2Name + "\" cannot be present at the same time" + - " on model \"logic\". Consider using only one of them."); - } - if ((!(attr1 instanceof Collection) && !(attr2 instanceof Collection) && attr1 != null && attr2 != null)) { - throw new BeatingAttributesException("Attributes \"" + attr1Name + "\" and \"" + attr2Name + "\" cannot be present at the same time" + - " on model \"logic\". Consider using only one of them."); - } - } -} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/ModelValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/ModelValidator.java deleted file mode 100644 index f12720bf98a..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/validation/ModelValidator.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.netgrif.application.engine.importer.service.validation; - - -import lombok.extern.slf4j.Slf4j; - -import java.util.Collection; - -@Slf4j -public abstract class ModelValidator implements IModelValidator { - - @Override - public void validateAttribute(Object attr, String attrName) { - if (attr instanceof Collection && !((Collection<?>) attr).isEmpty()) { - log.warn("Data attribute [" + attrName + "] is deprecated."); - } - - if (!(attr instanceof Collection) && attr != null) { - log.warn("Data attribute [" + attrName + "] is deprecated."); - } - } -} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/ProcessValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/ProcessValidator.java new file mode 100644 index 00000000000..cedbaedcfbb --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/validation/ProcessValidator.java @@ -0,0 +1,25 @@ +package com.netgrif.application.engine.importer.service.validation; + + +import com.netgrif.application.engine.petrinet.domain.Process; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@ConditionalOnProperty(prefix = "nae.importer", value = "validate-process", havingValue = "true", matchIfMissing = true) +public class ProcessValidator implements IProcessValidator { + + @Override + public void validate(Process process) { + // TODO: release/8.0.0 + // transitionValidator.checkDeprecatedAttributes(importTransition); +// logicValidator.checkConflictingAttributes(logic, logic.isAssigned(), logic.isAssign(), "assigned", "assign"); +// logicValidator.checkDeprecatedAttributes(logic); + // logicValidator.checkConflictingAttributes(logic, logic.isAssigned(), logic.isAssign(), "assigned", "assign"); +// logicValidator.checkDeprecatedAttributes(logic); + //// documentValidator.checkConflictingAttributes(process, process.getUsersRef(), process.getUserRef(), "usersRef", "userRef"); +//// documentValidator.checkDeprecatedAttributes(process); + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/SkipProcessValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/SkipProcessValidator.java new file mode 100644 index 00000000000..961a03f96a6 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/importer/service/validation/SkipProcessValidator.java @@ -0,0 +1,17 @@ +package com.netgrif.application.engine.importer.service.validation; + +import com.netgrif.application.engine.petrinet.domain.Process; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@ConditionalOnProperty(prefix = "nae.importer", value = "validate-process", havingValue = "false") +public class SkipProcessValidator implements IProcessValidator { + + @Override + public void validate(Process process) { + log.info("Skipping process validation"); + } +} diff --git a/src/main/java/com/netgrif/application/engine/importer/service/validation/TransitionValidator.java b/src/main/java/com/netgrif/application/engine/importer/service/validation/TransitionValidator.java deleted file mode 100644 index 4e4b69d49dd..00000000000 --- a/src/main/java/com/netgrif/application/engine/importer/service/validation/TransitionValidator.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.netgrif.application.engine.importer.service.validation; - -import com.netgrif.application.engine.importer.model.Transition; -import com.netgrif.application.engine.importer.service.throwable.BeatingAttributesException; -import org.springframework.stereotype.Component; - -import java.util.Collection; - -@Component -public class TransitionValidator extends ModelValidator implements ITransitionValidator { - - @Override - public void checkDeprecatedAttributes(Transition transition) { - validateAttribute(transition.getUsersRef(), "usersRef"); - } - - @Override - public void checkConflictingAttributes(Transition transition, Object attr1, Object attr2, String attr1Name, String attr2Name) throws BeatingAttributesException { - if ((attr1 instanceof Collection && attr2 instanceof Collection && !((Collection) attr1).isEmpty() && !((Collection) attr2).isEmpty())) { - throw new BeatingAttributesException("Attributes \"" + attr1Name + "\" and \"" + attr2Name + "\" cannot be present at the same time" + - " on model \"transition\" with ID \"" + transition.getId() + "\". Consider using only one of them."); - } - if ((!(attr1 instanceof Collection) && !(attr2 instanceof Collection) && attr1 != null && attr2 != null)) { - throw new BeatingAttributesException("Attributes \"" + attr1Name + "\" and \"" + attr2Name + "\" cannot be present at the same time" + - " on model \"transition\" with ID \"" + transition.getId() + "\". Consider using only one of them."); - } - } -} diff --git a/src/main/java/com/netgrif/application/engine/ldap/domain/LdapGroup.java b/src/main/java/com/netgrif/application/engine/ldap/domain/LdapGroup.java index 9ce24b39723..4d825e49ed1 100644 --- a/src/main/java/com/netgrif/application/engine/ldap/domain/LdapGroup.java +++ b/src/main/java/com/netgrif/application/engine/ldap/domain/LdapGroup.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.ldap.domain; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; +import com.netgrif.application.engine.authorization.domain.ProcessRole; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -28,6 +28,6 @@ public class LdapGroup { private String description; - private Set<ProcessRole> processesRoles; + private Set<ProcessRole> processesProcessRoles; } diff --git a/src/main/java/com/netgrif/application/engine/ldap/domain/LdapLoggedIdentity.java b/src/main/java/com/netgrif/application/engine/ldap/domain/LdapLoggedIdentity.java new file mode 100644 index 00000000000..b65d294ee6d --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/ldap/domain/LdapLoggedIdentity.java @@ -0,0 +1,63 @@ +package com.netgrif.application.engine.ldap.domain; + + +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; + +import java.util.Set; + +@Setter +@Getter +@ConditionalOnExpression("${nae.ldap.enabled:false}") +public class LdapLoggedIdentity extends LoggedIdentity { + + private String dn; + + private String commonName; + + private String uid; + + private Set<String> memberOf; + + private String homeDirectory; + + + public LdapLoggedIdentity(String id, String username, String password, String dn, String commonName, + Set<String> memberOf, String uid, String homeDirectory) { + super(null, id, null, username, password, null); + this.dn = dn; + this.commonName = commonName; + this.memberOf = memberOf; + this.uid = uid; + this.homeDirectory = homeDirectory; + } + +// public IUser transformToUser() { +// LdapUser user = new LdapUser(new ObjectId(this.id)); +// user.setEmail(getUsername()); +// String[] names = this.getFullName().split(" "); +// user.setName(names[0]); +// user.setSurname(names[1]); +// user.setDn(this.dn); +// user.setCommonName(this.commonName); +// user.setUid(this.uid); +// user.setMemberOf(this.memberOf); +// user.setHomeDirectory(homeDirectory); +// user.setState(IdentityState.ACTIVE); +// user.setPassword("n/a"); +// user.setAuthorities(getAuthorities().stream().map(a -> ((SessionRole) a)).collect(Collectors.toSet())); +//// user.setRoles(this.getRoles().stream().map(roleId -> { +//// Role role = new Role(); +//// role.setStringId(roleId); +//// return role; +//// }).collect(Collectors.toSet())); +// if (this.isImpersonating()) { +// user.setImpersonated(this.getImpersonated().transformToUser()); +// } +// return user; +// } + +} diff --git a/src/main/java/com/netgrif/application/engine/ldap/domain/LdapLoggedUser.java b/src/main/java/com/netgrif/application/engine/ldap/domain/LdapLoggedUser.java deleted file mode 100644 index c9390aace6b..00000000000 --- a/src/main/java/com/netgrif/application/engine/ldap/domain/LdapLoggedUser.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.netgrif.application.engine.ldap.domain; - - -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.domain.UserState; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import lombok.Getter; -import lombok.Setter; -import org.bson.types.ObjectId; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.security.core.GrantedAuthority; - -import java.util.Collection; -import java.util.Set; -import java.util.stream.Collectors; - -@ConditionalOnExpression("${nae.ldap.enabled:false}") -public class LdapLoggedUser extends LoggedUser { - - @Getter - @Setter - private String dn; - - @Getter - @Setter - private String commonName; - - @Getter - @Setter - private String uid; - - @Getter - @Setter - private Set<String> memberOf; - - @Getter - @Setter - private String homeDirectory; - - - public LdapLoggedUser(String id, String username, String password, Collection<? extends GrantedAuthority> authorities) { - super(id, username, password, authorities); - } - - - public LdapLoggedUser(String id, String username, String password, String dn, String commonName, Set<String> memberOf, String uid, String homeDirectory, Collection<? extends GrantedAuthority> authorities) { - super(id, username, password, authorities); - this.dn = dn; - this.commonName = commonName; - this.memberOf = memberOf; - this.uid = uid; - this.homeDirectory = homeDirectory; - } - - public IUser transformToUser() { - LdapUser user = new LdapUser(new ObjectId(this.id)); - user.setEmail(getUsername()); - String[] names = this.getFullName().split(" "); - user.setName(names[0]); - user.setSurname(names[1]); - user.setDn(this.dn); - user.setCommonName(this.commonName); - user.setUid(this.uid); - user.setMemberOf(this.memberOf); - user.setHomeDirectory(homeDirectory); - user.setState(UserState.ACTIVE); - user.setPassword("n/a"); - user.setAuthorities(getAuthorities().stream().map(a -> ((Authority) a)).collect(Collectors.toSet())); - user.setProcessRoles(this.getProcessRoles().stream().map(roleId -> { - ProcessRole role = new ProcessRole(); - role.setId(roleId); - return role; - }).collect(Collectors.toSet())); - if (this.isImpersonating()) { - user.setImpersonated(this.getImpersonated().transformToUser()); - } - return user; - } - -} diff --git a/src/main/java/com/netgrif/application/engine/ldap/domain/LdapUser.java b/src/main/java/com/netgrif/application/engine/ldap/domain/LdapUser.java deleted file mode 100644 index ff9113d73b2..00000000000 --- a/src/main/java/com/netgrif/application/engine/ldap/domain/LdapUser.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.netgrif.application.engine.ldap.domain; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.domain.User; -import lombok.Data; -import org.bson.types.ObjectId; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.data.mongodb.core.index.Indexed; -import org.springframework.data.mongodb.core.mapping.Document; - -import java.util.HashSet; -import java.util.Set; - - -@Data -@Document(collection = "user") -@ConditionalOnExpression("${nae.ldap.enabled:false}") -public class LdapUser extends User { - - @Indexed - private String dn; - - private String commonName; - - private String uid; - - private String homeDirectory; - - private Set<String> memberOf; - - public LdapUser() { - } - - public LdapUser(ObjectId id) { - this(); - this.id = id; - nextGroups = new HashSet<>(); - } - - public LdapUser(String dn, String commonName, String uid, String homeDirectory, - String email, String name, String surname, Set<String> memberOf, String telNumber) { - this.setEmail(email); - this.setName(name); - this.setSurname(surname); - this.setDn(dn); - this.setCommonName(commonName); - this.setUid(uid); - this.setHomeDirectory(homeDirectory); - this.setMemberOf(memberOf); - this.setTelNumber(telNumber); - - } - - @Override - public String getStringId() { - return id.toString(); - } - - - @Override - public LoggedUser transformToLoggedUser() { - LdapLoggedUser loggedUser = new LdapLoggedUser(this.getStringId(), this.getEmail(), this.getPassword(), getDn(), getCommonName(), getMemberOf(), getUid(), getHomeDirectory(), this.getAuthorities()); - loggedUser.setFullName(this.getFullName()); - if (!this.getProcessRoles().isEmpty()) - loggedUser.parseProcessRoles(this.getProcessRoles()); - loggedUser.setGroups(this.getNextGroups()); - if (this.isImpersonating()) { - loggedUser.impersonate(this.getImpersonated().transformToLoggedUser()); - } - - return loggedUser; - } - - public void loadFromUser(IUser user) { - this.setEmail(user.getEmail()); - this.setName(user.getName()); - this.setSurname(user.getSurname()); - this.setAvatar(user.getAvatar()); - this.setTelNumber(user.getTelNumber()); - this.setNextGroups(user.getNextGroups()); - this.setProcessRoles(user.getProcessRoles()); - this.setState(user.getState()); - } -} diff --git a/src/main/java/com/netgrif/application/engine/ldap/domain/repository/LdapUserRepository.java b/src/main/java/com/netgrif/application/engine/ldap/domain/repository/LdapUserRepository.java deleted file mode 100644 index cd0081708c5..00000000000 --- a/src/main/java/com/netgrif/application/engine/ldap/domain/repository/LdapUserRepository.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.netgrif.application.engine.ldap.domain.repository; - - -import com.netgrif.application.engine.ldap.domain.LdapUser; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.mongodb.repository.MongoRepository; -import org.springframework.data.querydsl.QuerydslPredicateExecutor; -import org.springframework.stereotype.Repository; - -import java.util.List; - - -@Repository -@ConditionalOnExpression("${nae.ldap.enabled:false}") -public interface LdapUserRepository extends MongoRepository<LdapUser, String>, QuerydslPredicateExecutor<LdapUser> { - - LdapUser findByDn(String dn); - - LdapUser findByEmail(String email); - - List<LdapUser> findAll(); - - Page<LdapUser> findDistinctByDnIn(Iterable<String> dns, Pageable pageable); - -} diff --git a/src/main/java/com/netgrif/application/engine/ldap/service/LdapGroupRefService.java b/src/main/java/com/netgrif/application/engine/ldap/service/LdapGroupRefService.java index b94c7c36e50..a786eee7a92 100644 --- a/src/main/java/com/netgrif/application/engine/ldap/service/LdapGroupRefService.java +++ b/src/main/java/com/netgrif/application/engine/ldap/service/LdapGroupRefService.java @@ -1,15 +1,17 @@ package com.netgrif.application.engine.ldap.service; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; import com.netgrif.application.engine.configuration.ldap.LdapConfiguration; import com.netgrif.application.engine.configuration.properties.NaeLdapProperties; import com.netgrif.application.engine.ldap.domain.LdapGroup; import com.netgrif.application.engine.ldap.domain.LdapGroupRef; import com.netgrif.application.engine.ldap.domain.repository.LdapGroupRoleRepository; import com.netgrif.application.engine.ldap.service.interfaces.ILdapGroupRefService; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; +import com.netgrif.application.engine.authorization.domain.ProcessRole; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.ldap.core.ContextMapper; @@ -35,15 +37,15 @@ public class LdapGroupRefService implements ILdapGroupRefService { private final LdapGroupRoleRepository ldapGroupRoleRepository; - private final IProcessRoleService processRoleService; + private final IRoleService roleService; private final NaeLdapProperties ldapProperties; public LdapGroupRefService(LdapConfiguration ldapConfiguration, LdapGroupRoleRepository ldapGroupRoleRepository, - IProcessRoleService processRoleService, NaeLdapProperties ldapProperties) { + IRoleService roleService, NaeLdapProperties ldapProperties) { this.ldapConfiguration = ldapConfiguration; this.ldapGroupRoleRepository = ldapGroupRoleRepository; - this.processRoleService = processRoleService; + this.roleService = roleService; this.ldapProperties = ldapProperties; } @@ -79,45 +81,47 @@ public List<LdapGroup> getAllLdapGroupRoles() { } @Override - public void deleteProcessRoleByPetrinet(String petriNet) { - ldapGroupRoleRepository.findAll().stream() - .filter(ldapGroup -> ldapGroup.getProcessesRoles().stream().anyMatch(processRole -> processRole.getNetId().equals(petriNet))) - .forEach(it -> deleteProcessRole(it, petriNet)); + public void deleteRoleByPetriNet(String petriNet) { + // TODO: release/8.0.0 +// ldapGroupRoleRepository.findAll().stream() +// .filter(ldapGroup -> ldapGroup.getProcessesRoles().stream().anyMatch(processRole -> processRole.getNetId().equals(petriNet))) +// .forEach(it -> deleteProcessRole(it, petriNet)); } @Override - public void deleteProcessRole(LdapGroup ldapGroup, String petriNet) { - Set<ProcessRole> processRoles = ldapGroup.getProcessesRoles(); - processRoles.forEach(it -> { - if (it.getNetId().equals(petriNet)) { - processRoles.remove(it); - } - }); - ldapGroup.setProcessesRoles(processRoles); - ldapGroupRoleRepository.save(ldapGroup); + public void deleteRole(LdapGroup ldapGroup, String petriNet) { +// TODO: release/8.0.0 +// Set<ProcessRole> processRoles = ldapGroup.getProcessesRoles(); +// processRoles.forEach(it -> { +// if (it.getNetId().equals(petriNet)) { +// processRoles.remove(it); +// } +// }); +// ldapGroup.setProcessesRoles(processRoles); +// ldapGroupRoleRepository.save(ldapGroup); } @Override - public Set<ProcessRole> getProcessRoleByLdapGroup(Set<String> groupDn) { - return ldapGroupRoleRepository.findAllByDnIn(groupDn).stream().map(LdapGroup::getProcessesRoles).flatMap(Collection::stream).collect(Collectors.toSet()); + public Set<ProcessRole> getRoleByLdapGroup(Set<String> groupDn) { + return ldapGroupRoleRepository.findAllByDnIn(groupDn).stream().map(LdapGroup::getProcessesProcessRoles).flatMap(Collection::stream).collect(Collectors.toSet()); } @Override - public void setRoleToLdapGroup(String groupDn, Set<String> requestedRolesIds, LoggedUser loggedUser) { - Set<ProcessRole> requestedRoles = processRoleService.findByIds(requestedRolesIds); - if (requestedRoles.isEmpty() && !requestedRolesIds.isEmpty()) + public void setRoleToLdapGroup(String groupDn, Set<String> requestedRolesIds, LoggedIdentity identity) { + List<Role> requestedProcessRoles = roleService.findAllById(requestedRolesIds); + if (requestedProcessRoles.isEmpty() && !requestedRolesIds.isEmpty()) throw new IllegalArgumentException("No process roles found."); - if (requestedRoles.size() != requestedRolesIds.size()) + if (requestedProcessRoles.size() != requestedRolesIds.size()) throw new IllegalArgumentException("Not all process roles were found!"); LdapGroup ldapGroup = ldapGroupRoleRepository.findByDn(groupDn); if (ldapGroup == null) { LdapGroup newLdapGroup = new LdapGroup(); newLdapGroup.setDn(groupDn); - newLdapGroup.setProcessesRoles(requestedRoles); +// newLdapGroup.setProcessesProcessRoles(requestedProcessRoles); ldapGroupRoleRepository.save(newLdapGroup); } else { - ldapGroup.setProcessesRoles(requestedRoles); +// ldapGroup.setProcessesProcessRoles(requestedProcessRoles); ldapGroupRoleRepository.save(ldapGroup); } diff --git a/src/main/java/com/netgrif/application/engine/ldap/service/LdapUserRefService.java b/src/main/java/com/netgrif/application/engine/ldap/service/LdapUserRefService.java index 71bf9e94169..18d111a2a3e 100644 --- a/src/main/java/com/netgrif/application/engine/ldap/service/LdapUserRefService.java +++ b/src/main/java/com/netgrif/application/engine/ldap/service/LdapUserRefService.java @@ -1,20 +1,13 @@ package com.netgrif.application.engine.ldap.service; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.UserState; -import com.netgrif.application.engine.auth.service.interfaces.ILdapUserRefService; +import com.netgrif.application.engine.authentication.service.interfaces.ILdapUserRefService; import com.netgrif.application.engine.configuration.ldap.LdapConfiguration; import com.netgrif.application.engine.configuration.properties.NaeLdapProperties; -import com.netgrif.application.engine.event.events.user.UserRegistrationEvent; -import com.netgrif.application.engine.ldap.domain.LdapUser; import com.netgrif.application.engine.ldap.domain.LdapUserRef; import com.netgrif.application.engine.ldap.domain.repository.LdapUserRefRepository; import com.netgrif.application.engine.ldap.service.interfaces.ILdapGroupRefService; -import com.netgrif.application.engine.orgstructure.groups.config.GroupConfigurationProperties; -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.context.ApplicationEventPublisher; @@ -45,47 +38,41 @@ public class LdapUserRefService implements ILdapUserRefService { @Autowired private LdapUserRefRepository repository; - @Autowired - private LdapUserService ldapUserService; - - @Autowired - private INextGroupService groupService; +// @Autowired +// private LdapUserService ldapUserService; @Autowired private ApplicationEventPublisher publisher; - @Autowired - private GroupConfigurationProperties groupProperties; - @Autowired private NaeLdapProperties ldapProperties; @Autowired private LdapConfiguration ldapUserConfiguration; - @Override - public IUser createUser(LdapUserRef ldapUserRef) { - LdapUser ldapUser = new LdapUser(ldapUserRef.getDn().toString(), ldapUserRef.getCn(), ldapUserRef.getUid(), ldapUserRef.getHomeDirectory(), ldapUserRef.getMail(), ldapUserRef.getFirstName(), ldapUserRef.getSurname(), ldapUserRef.getMemberOf(), ldapUserRef.getTelNumber()); - ldapUser.setToken(null); - ldapUser.setExpirationDate(null); - ldapUser.setState(UserState.ACTIVE); - - String generatedString = RandomStringUtils.randomAlphanumeric(35); - ldapUser.setPassword(generatedString); - LdapUser savedUser = (LdapUser) ldapUserService.saveNew(ldapUser); - savedUser.setNextGroups(this.groupService.getAllGroupsOfUser(savedUser)); - - if (groupProperties.isDefaultEnabled()) - groupService.createGroup(savedUser); - - if (groupProperties.isSystemEnabled()) - groupService.addUserToDefaultGroup(savedUser); - - publisher.publishEvent(new UserRegistrationEvent(savedUser)); - - savedUser.setPassword("n/a"); - return ldapUserService.save(savedUser); - } +// @Override +// public IUser createUser(LdapUserRef ldapUserRef) { +// LdapUser ldapUser = new LdapUser(ldapUserRef.getDn().toString(), ldapUserRef.getCn(), ldapUserRef.getUid(), ldapUserRef.getHomeDirectory(), ldapUserRef.getMail(), ldapUserRef.getFirstName(), ldapUserRef.getSurname(), ldapUserRef.getMemberOf(), ldapUserRef.getTelNumber()); +// ldapUser.setToken(null); +// ldapUser.setExpirationDate(null); +// ldapUser.setState(IdentityState.ACTIVE); +// +// String generatedString = RandomStringUtils.randomAlphanumeric(35); +// ldapUser.setPassword(generatedString); +// LdapUser savedUser = (LdapUser) ldapUserService.saveNew(ldapUser); +// savedUser.setNextGroups(this.groupService.getAllGroupsOfUser(savedUser)); +// +// if (groupProperties.isDefaultEnabled()) +// groupService.createGroup(savedUser); +// +// if (groupProperties.isSystemEnabled()) +// groupService.addUserToDefaultGroup(savedUser); +// +// publisher.publishEvent(new UserRegistrationEvent(savedUser)); +// +// savedUser.setPassword("n/a"); +// return ldapUserService.save(savedUser); +// } @Override public LdapUserRef findById(Name id) { @@ -130,37 +117,37 @@ private String verificationData(DirContextOperations context, String attribute) } - @Override - public IUser updateById(Name id, IUser savedUser) { - DirContextOperations context = ldapUserConfiguration.ldapTemplate().lookupContext(id); - context.setAttributeValues("objectClass", ldapProperties.getPeopleClass()); - LdapUserRef user = new LdapUserRef(); - user.setUid(verificationData(context, ldapProperties.getMapUid())); - user.setMail(verificationData(context, ldapProperties.getMapMail())); - user.setFirstName(verificationData(context, ldapProperties.getMapFirstName())); - user.setSurname(verificationData(context, ldapProperties.getMapSurname())); - user.setTelNumber(verificationData(context, ldapProperties.getMapTelNumber())); - user.setCn(verificationData(context, ldapProperties.getMapCn())); - user.setFullName(verificationData(context, ldapProperties.getMapDisplayName())); - LdapQuery findAllGroupsGetMemberQuery = - Arrays.stream(ldapProperties.getGroupClass()).map(it -> query().where("objectclass").is(it)).reduce(ContainerCriteria::and) - .orElse(query().where("objectclass").is(ldapProperties.getGroupClass()[0])) - .and((query().where(ldapProperties.getMapGroupMember()).is(((DirContextAdapter) context).getDn().toString() + "," + ldapUserConfiguration.contextSource().getBaseLdapPathAsString()))); - List<DirContextAdapter> ldapGroups = ldapUserConfiguration.ldapTemplate().search(findAllGroupsGetMemberQuery, (ContextMapper) ctx -> ((DirContextAdapter) ctx)); - user.setMemberOf(ldapGroups.stream().map(DirContextAdapter::getDn).map(Objects::toString).collect(Collectors.toSet())); - user.setHomeDirectory(verificationData(context, ldapProperties.getMapHomeDirectory())); - LdapUser ldapUser = (LdapUser) savedUser; - - ldapUser.setCommonName(user.getCn()); - ldapUser.setUid(user.getUid()); - ldapUser.setHomeDirectory(user.getHomeDirectory()); - ldapUser.setEmail(user.getMail()); - ldapUser.setTelNumber(user.getTelNumber()); - ldapUser.setName(user.getFirstName()); - ldapUser.setMemberOf(user.getMemberOf()); - ldapUser.setSurname(user.getSurname()); - return ldapUserService.save(ldapUser); - } +// @Override +// public IUser updateById(Name id, IUser savedUser) { +// DirContextOperations context = ldapUserConfiguration.ldapTemplate().lookupContext(id); +// context.setAttributeValues("objectClass", ldapProperties.getPeopleClass()); +// LdapUserRef user = new LdapUserRef(); +// user.setUid(verificationData(context, ldapProperties.getMapUid())); +// user.setMail(verificationData(context, ldapProperties.getMapMail())); +// user.setFirstName(verificationData(context, ldapProperties.getMapFirstName())); +// user.setSurname(verificationData(context, ldapProperties.getMapSurname())); +// user.setTelNumber(verificationData(context, ldapProperties.getMapTelNumber())); +// user.setCn(verificationData(context, ldapProperties.getMapCn())); +// user.setFullName(verificationData(context, ldapProperties.getMapDisplayName())); +// LdapQuery findAllGroupsGetMemberQuery = +// Arrays.stream(ldapProperties.getGroupClass()).map(it -> query().where("objectclass").is(it)).reduce(ContainerCriteria::and) +// .orElse(query().where("objectclass").is(ldapProperties.getGroupClass()[0])) +// .and((query().where(ldapProperties.getMapGroupMember()).is(((DirContextAdapter) context).getDn().toString() + "," + ldapUserConfiguration.contextSource().getBaseLdapPathAsString()))); +// List<DirContextAdapter> ldapGroups = ldapUserConfiguration.ldapTemplate().search(findAllGroupsGetMemberQuery, (ContextMapper) ctx -> ((DirContextAdapter) ctx)); +// user.setMemberOf(ldapGroups.stream().map(DirContextAdapter::getDn).map(Objects::toString).collect(Collectors.toSet())); +// user.setHomeDirectory(verificationData(context, ldapProperties.getMapHomeDirectory())); +// LdapUser ldapUser = (LdapUser) savedUser; +// +// ldapUser.setCommonName(user.getCn()); +// ldapUser.setUid(user.getUid()); +// ldapUser.setHomeDirectory(user.getHomeDirectory()); +// ldapUser.setEmail(user.getMail()); +// ldapUser.setTelNumber(user.getTelNumber()); +// ldapUser.setName(user.getFirstName()); +// ldapUser.setMemberOf(user.getMemberOf()); +// ldapUser.setSurname(user.getSurname()); +// return ldapUserService.save(ldapUser); +// } @Override diff --git a/src/main/java/com/netgrif/application/engine/ldap/service/LdapUserService.java b/src/main/java/com/netgrif/application/engine/ldap/service/LdapUserService.java index eb62d8b2995..3965278b865 100644 --- a/src/main/java/com/netgrif/application/engine/ldap/service/LdapUserService.java +++ b/src/main/java/com/netgrif/application/engine/ldap/service/LdapUserService.java @@ -1,12 +1,8 @@ package com.netgrif.application.engine.ldap.service; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.service.UserService; -import com.netgrif.application.engine.ldap.domain.LdapUser; -import com.netgrif.application.engine.ldap.domain.repository.LdapUserRepository; +import com.netgrif.application.engine.authentication.domain.Identity; import lombok.extern.slf4j.Slf4j; -import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.context.annotation.Primary; @@ -18,44 +14,42 @@ @Service @Primary @ConditionalOnExpression("${nae.ldap.enabled:false}") -public class LdapUserService extends UserService { - - @Autowired - private LdapUserRepository ldapUserRepository; +public class LdapUserService /*extends UserService*/ { @Autowired private LdapGroupRefService ldapGroupRefService; - public LdapUser findByDn(Name dn) { - return ldapUserRepository.findByDn(dn.toString()); - } - - @Override - public IUser findByEmail(String email) { - IUser user = userRepository.findByEmail(email); - if (user instanceof LdapUser && (((LdapUser) user).getMemberOf() != null && !(((LdapUser) user).getMemberOf().isEmpty()))) { - ldapGroupRefService.getProcessRoleByLdapGroup(((LdapUser) user).getMemberOf()).forEach(user::addProcessRole); - } - return user; + public Identity findByDn(Name dn) { +// return ldapUserRepository.findByDn(dn.toString()); + return null; } - protected LdapUser getUserFromLdap(IUser user) { - if (user instanceof LdapUser) { - return (LdapUser) user; - } else { - return transformToUserFromLdap(user); - } - } - - - public LdapUser transformToUserFromLdap(IUser user) { - LdapUser userFromLdap = ldapUserRepository.findByEmail(user.getEmail()); - if (userFromLdap == null && user.getStringId() != null) { - userFromLdap = new LdapUser(new ObjectId(user.getStringId())); - } else if (userFromLdap == null) { - userFromLdap = new LdapUser(); - } - userFromLdap.loadFromUser(user); - return userFromLdap; - } +// @Override +// public IUser findByEmail(String email) { +// IUser user = userRepository.findByEmail(email); +// if (user instanceof LdapUser && (((LdapUser) user).getMemberOf() != null && !(((LdapUser) user).getMemberOf().isEmpty()))) { +//// ldapGroupRefService.getRoleByLdapGroup(((LdapUser) user).getMemberOf()).forEach(user::addRole); +// } +// return user; +// } +// +// protected LdapUser getUserFromLdap(IUser user) { +// if (user instanceof LdapUser) { +// return (LdapUser) user; +// } else { +// return transformToUserFromLdap(user); +// } +// } +// +// +// public LdapUser transformToUserFromLdap(IUser user) { +// LdapUser userFromLdap = ldapUserRepository.findByEmail(user.getEmail()); +// if (userFromLdap == null && user.getStringId() != null) { +// userFromLdap = new LdapUser(new ObjectId(user.getStringId())); +// } else if (userFromLdap == null) { +// userFromLdap = new LdapUser(); +// } +// userFromLdap.loadFromUser(user); +// return userFromLdap; +// } } diff --git a/src/main/java/com/netgrif/application/engine/ldap/service/interfaces/ILdapGroupRefService.java b/src/main/java/com/netgrif/application/engine/ldap/service/interfaces/ILdapGroupRefService.java index f5e932e25d5..cd56e4cdd83 100644 --- a/src/main/java/com/netgrif/application/engine/ldap/service/interfaces/ILdapGroupRefService.java +++ b/src/main/java/com/netgrif/application/engine/ldap/service/interfaces/ILdapGroupRefService.java @@ -1,9 +1,9 @@ package com.netgrif.application.engine.ldap.service.interfaces; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.ldap.domain.LdapGroup; import com.netgrif.application.engine.ldap.domain.LdapGroupRef; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; +import com.netgrif.application.engine.authorization.domain.ProcessRole; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.ldap.query.LdapQuery; @@ -13,20 +13,20 @@ @ConditionalOnExpression("${nae.ldap.enabled:false}") public interface ILdapGroupRefService { - public List<LdapGroupRef> findAllGroups(); + List<LdapGroupRef> findAllGroups(); - public List<LdapGroupRef> searchGroups(String searchText); + List<LdapGroupRef> searchGroups(String searchText); List<LdapGroupRef> searchGroups(LdapQuery ldapQuery); - public List<LdapGroup> getAllLdapGroupRoles(); + List<LdapGroup> getAllLdapGroupRoles(); - void deleteProcessRoleByPetrinet(String petrinet); + void deleteRoleByPetriNet(String petriNet); - void deleteProcessRole(LdapGroup ldapGroup, String petriNet); + void deleteRole(LdapGroup ldapGroup, String petriNet); - Set<ProcessRole> getProcessRoleByLdapGroup(Set<String> groupDn); + Set<ProcessRole> getRoleByLdapGroup(Set<String> groupDn); - public void setRoleToLdapGroup(String groupDn, Set<String> roleIds, LoggedUser loggedUser); + void setRoleToLdapGroup(String groupDn, Set<String> roleIds, LoggedIdentity identity); } diff --git a/src/main/java/com/netgrif/application/engine/mail/MailService.java b/src/main/java/com/netgrif/application/engine/mail/MailService.java index 086967a3fc0..6d453fffb6f 100644 --- a/src/main/java/com/netgrif/application/engine/mail/MailService.java +++ b/src/main/java/com/netgrif/application/engine/mail/MailService.java @@ -1,7 +1,7 @@ package com.netgrif.application.engine.mail; -import com.netgrif.application.engine.auth.domain.RegisteredUser; -import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.service.interfaces.IRegistrationService; import com.netgrif.application.engine.configuration.properties.ServerAuthProperties; import com.netgrif.application.engine.mail.domain.MailDraft; import com.netgrif.application.engine.mail.interfaces.IMailService; @@ -68,12 +68,12 @@ public class MailService implements IMailService { private ServerAuthProperties serverAuthProperties; @Override - public void sendRegistrationEmail(RegisteredUser user) throws MessagingException, IOException, TemplateException { + public void sendRegistrationEmail(Identity identity) throws MessagingException, IOException, TemplateException { List<String> recipients = new LinkedList<>(); Map<String, Object> model = new HashMap<>(); - recipients.add(user.getEmail()); - model.put(TOKEN, registrationService.encodeToken(user.getEmail(), user.getToken())); + recipients.add(identity.getUsername()); + model.put(TOKEN, registrationService.encodeToken(identity.getUsername(), identity.getRegistrationToken())); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); model.put(VALIDITY, "" + serverAuthProperties.getTokenValidityPeriod()); model.put(EXPIRATION, registrationService.generateExpirationDate().format(formatter)); @@ -84,25 +84,27 @@ public void sendRegistrationEmail(RegisteredUser user) throws MessagingException MimeMessage email = buildEmail(mailDraft); mailSender.send(email); - log.info("Registration email sent to [" + user.getEmail() + "] with token [" + model.get(TOKEN) + "], expiring on [" + model.get(EXPIRATION) + "]"); + log.info("Registration email sent to [{}] with token [{}], expiring on [{}]", identity.getUsername(), + model.get(TOKEN), model.get(EXPIRATION)); } @Override - public void sendPasswordResetEmail(RegisteredUser user) throws MessagingException, IOException, TemplateException { + public void sendPasswordResetEmail(Identity identity) throws MessagingException, IOException, TemplateException { Map<String, Object> model = new HashMap<>(); - model.put(NAME, user.getName()); - model.put(TOKEN, registrationService.encodeToken(user.getEmail(), user.getToken())); + model.put(NAME, identity.getFullName()); + model.put(TOKEN, registrationService.encodeToken(identity.getUsername(), identity.getRegistrationToken())); model.put(VALIDITY, "" + serverAuthProperties.getTokenValidityPeriod()); model.put(EXPIRATION, registrationService.generateExpirationDate().format(DateTimeFormatter.ofPattern("dd.MM.yyyy"))); model.put(SERVER, getServerURL()); - MailDraft mailDraft = MailDraft.builder(mailFrom, Collections.singletonList(user.getEmail())).subject(EmailType.PASSWORD_RESET.getSubject()) + MailDraft mailDraft = MailDraft.builder(mailFrom, Collections.singletonList(identity.getUsername())).subject(EmailType.PASSWORD_RESET.getSubject()) .body(configuration.getTemplate(EmailType.PASSWORD_RESET.template).toString()).model(model).build(); MimeMessage email = buildEmail(mailDraft); mailSender.send(email); - log.info("Reset email sent to [" + user.getEmail() + "] with token [" + model.get(TOKEN) + "], expiring on [" + model.get(EXPIRATION) + "]"); + log.info("Reset email sent to [{}] with token [{}], expiring on [{}]", identity.getUsername(), model.get(TOKEN), + model.get(EXPIRATION)); } @Override @@ -122,7 +124,7 @@ public void sendMail(MailDraft mailDraft) throws MessagingException, IOException mailSender.send(email); String formattedRecipients = StringUtils.join(mailDraft.getTo(), ", "); - log.info("Email sent to [" + formattedRecipients + "]"); + log.info("Email sent to [{}]", formattedRecipients); } protected MimeMessage buildEmail(MailDraft draft) throws MessagingException, IOException, TemplateException { diff --git a/src/main/java/com/netgrif/application/engine/mail/interfaces/IMailService.java b/src/main/java/com/netgrif/application/engine/mail/interfaces/IMailService.java index 0004508ad6d..6c09cd9f83a 100644 --- a/src/main/java/com/netgrif/application/engine/mail/interfaces/IMailService.java +++ b/src/main/java/com/netgrif/application/engine/mail/interfaces/IMailService.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.mail.interfaces; -import com.netgrif.application.engine.auth.domain.RegisteredUser; +import com.netgrif.application.engine.authentication.domain.Identity; import com.netgrif.application.engine.mail.domain.MailDraft; import freemarker.template.TemplateException; @@ -9,9 +9,9 @@ public interface IMailService { - void sendRegistrationEmail(RegisteredUser user) throws MessagingException, IOException, TemplateException; + void sendRegistrationEmail(Identity identity) throws MessagingException, IOException, TemplateException; - void sendPasswordResetEmail(RegisteredUser user) throws MessagingException, IOException, TemplateException; + void sendPasswordResetEmail(Identity identity) throws MessagingException, IOException, TemplateException; void testConnection(); diff --git a/src/main/java/com/netgrif/application/engine/manager/service/SessionManagerService.java b/src/main/java/com/netgrif/application/engine/manager/service/SessionManagerService.java index 6ca4bc5c446..638114c70a6 100644 --- a/src/main/java/com/netgrif/application/engine/manager/service/SessionManagerService.java +++ b/src/main/java/com/netgrif/application/engine/manager/service/SessionManagerService.java @@ -1,10 +1,13 @@ package com.netgrif.application.engine.manager.service; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.security.service.SecurityContextService; +import com.netgrif.application.engine.startup.SystemUserRunner; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisOperations; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextImpl; import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository; @@ -22,39 +25,74 @@ public class SessionManagerService implements ISessionManagerService { protected final RedisIndexedSessionRepository repository; protected final SessionRegistry sessionRegistry; + protected final SecurityContextService securityContextService; + protected final SystemUserRunner systemUserRunner; protected final String redisUsernameKey; - public SessionManagerService(RedisIndexedSessionRepository repository, SessionRegistry sessionRegistry, @Value("${spring.session.redis.namespace}") String redisNamespace) { + public SessionManagerService(RedisIndexedSessionRepository repository, SessionRegistry sessionRegistry, + SecurityContextService securityContextService, SystemUserRunner systemUserRunner, + @Value("${spring.session.redis.namespace}") String redisNamespace) { this.repository = repository; this.sessionRegistry = sessionRegistry; - this.redisUsernameKey = RedisIndexedSessionRepository.DEFAULT_NAMESPACE + ":" + redisNamespace + ":index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:"; + this.securityContextService = securityContextService; + this.systemUserRunner = systemUserRunner; + this.redisUsernameKey = RedisIndexedSessionRepository.DEFAULT_NAMESPACE + ":" + redisNamespace + + ":index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:"; } + /** + * Gets currently logged identity + * + * @return Currently logged identity. Can be null if nobody is logged in. + */ @Override - public List<LoggedUser> getAllLoggedUsers() { + public LoggedIdentity getLoggedIdentity() { + if (securityContextService.isAuthenticatedPrincipalLoggedIdentity()) { + return (LoggedIdentity) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + } + return null; + } + + /** + * Gets id of currently selected actor of logged identity + * + * @return The id of the selected actor if any identity is logged in. Can be null. + */ + @Override + public String getActiveActorId() { + LoggedIdentity loggedIdentity = getLoggedIdentity(); + if (loggedIdentity != null) { + return loggedIdentity.getActiveActorId(); + } + return null; + } + + @Override + public List<LoggedIdentity> getAllLoggedIdentities() { RedisOperations<Object, Object> redisOps = repository.getSessionRedisOperations(); if (redisOps == null) { throw new IllegalStateException("Redis session management is not configured!"); } - List<LoggedUser> activeUsers = new ArrayList<>(); + List<LoggedIdentity> activeIdentities = new ArrayList<>(); Set<Object> keys = redisOps.keys(redisUsernameKey + "*"); if (keys == null || keys.isEmpty()) { - return activeUsers; + return activeIdentities; } keys.forEach(username -> { - Session session = repository.findByPrincipalName(username.toString().replace(redisUsernameKey, "")).values().stream().findFirst().orElse(null); + Session session = repository.findByPrincipalName(username.toString().replace(redisUsernameKey, "")) + .values().stream().findFirst().orElse(null); if (session != null) { - SecurityContextImpl impl = (SecurityContextImpl) session.getAttribute(WebSessionServerSecurityContextRepository.DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME); + SecurityContextImpl impl = session.getAttribute(WebSessionServerSecurityContextRepository.DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME); if (impl != null) { - LoggedUser user = (LoggedUser) impl.getAuthentication().getPrincipal(); - if (user != null) { - activeUsers.add(user); + LoggedIdentity identity = (LoggedIdentity) impl.getAuthentication().getPrincipal(); + if (identity != null) { + activeIdentities.add(identity); } } } }); - return activeUsers; + return activeIdentities; } @Override @@ -64,8 +102,9 @@ public void logoutSessionByUsername(String username) { @Override public void logoutAllSession() { - List<LoggedUser> users = getAllLoggedUsers(); - users.forEach(loggedUser -> repository.findByPrincipalName(loggedUser.getEmail()).keySet().forEach(repository::deleteById)); + List<LoggedIdentity> loggedIdentities = getAllLoggedIdentities(); + loggedIdentities.forEach(loggedUser -> repository.findByPrincipalName(loggedUser.getUsername()) + .keySet().forEach(repository::deleteById)); } } diff --git a/src/main/java/com/netgrif/application/engine/manager/service/interfaces/ISessionManagerService.java b/src/main/java/com/netgrif/application/engine/manager/service/interfaces/ISessionManagerService.java index f57c45ff3b5..6020b278ac3 100644 --- a/src/main/java/com/netgrif/application/engine/manager/service/interfaces/ISessionManagerService.java +++ b/src/main/java/com/netgrif/application/engine/manager/service/interfaces/ISessionManagerService.java @@ -1,12 +1,16 @@ package com.netgrif.application.engine.manager.service.interfaces; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import java.util.Collection; public interface ISessionManagerService { - Collection<LoggedUser> getAllLoggedUsers(); + LoggedIdentity getLoggedIdentity(); + + String getActiveActorId(); + + Collection<LoggedIdentity> getAllLoggedIdentities(); void logoutSessionByUsername(String username); diff --git a/src/main/java/com/netgrif/application/engine/manager/web/SessionManagerController.java b/src/main/java/com/netgrif/application/engine/manager/web/SessionManagerController.java index f95f1613f37..fff046899e1 100644 --- a/src/main/java/com/netgrif/application/engine/manager/web/SessionManagerController.java +++ b/src/main/java/com/netgrif/application/engine/manager/web/SessionManagerController.java @@ -1,17 +1,17 @@ package com.netgrif.application.engine.manager.web; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; import com.netgrif.application.engine.manager.web.body.request.LogoutRequest; -import com.netgrif.application.engine.manager.web.body.response.AllLoggedUsersResponse; +import com.netgrif.application.engine.manager.web.body.response.AllLoggedIdentitiesResponse; import com.netgrif.application.engine.manager.web.body.response.MessageLogoutResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.hateoas.MediaTypes; import org.springframework.security.access.prepost.PreAuthorize; @@ -21,6 +21,7 @@ @Slf4j @RestController() +@RequiredArgsConstructor @RequestMapping("/api/manager/session") @ConditionalOnProperty( value = "nae.session.web.enabled", @@ -30,11 +31,10 @@ @Tag(name = "Session Manager") public class SessionManagerController { - @Autowired - private ISessionManagerService sessionManagerService; + private final ISessionManagerService sessionManagerService; - @PreAuthorize("hasRole('ADMIN')") - @Operation(summary = "Get All logged users", + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") + @Operation(summary = "Get All logged identities", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/all", produces = MediaTypes.HAL_JSON_VALUE) @@ -42,13 +42,13 @@ public class SessionManagerController { @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), }) - public AllLoggedUsersResponse getAllSessions() { - Collection<LoggedUser> loggedUsers = sessionManagerService.getAllLoggedUsers(); - return new AllLoggedUsersResponse(loggedUsers); + public AllLoggedIdentitiesResponse getAllSessions() { + Collection<LoggedIdentity> identities = sessionManagerService.getAllLoggedIdentities(); + return new AllLoggedIdentitiesResponse(identities); } - @PreAuthorize("hasRole('ADMIN')") - @Operation(summary = "Logout current user", + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") + @Operation(summary = "Logout current identity", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/logout", produces = MediaTypes.HAL_JSON_VALUE) @@ -58,12 +58,12 @@ public AllLoggedUsersResponse getAllSessions() { }) public MessageLogoutResponse logoutCurrentSession(@RequestBody LogoutRequest requestBody) { - requestBody.getUsers().forEach(user -> sessionManagerService.logoutSessionByUsername(user)); + requestBody.getIdentities().forEach(sessionManagerService::logoutSessionByUsername); return new MessageLogoutResponse(true); } - @PreAuthorize("hasRole('ADMIN')") - @Operation(summary = "Logout all user", + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") + @Operation(summary = "Logout all identities", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/logout/all", produces = MediaTypes.HAL_JSON_VALUE) diff --git a/src/main/java/com/netgrif/application/engine/manager/web/body/request/LogoutRequest.java b/src/main/java/com/netgrif/application/engine/manager/web/body/request/LogoutRequest.java index 416c793c147..c4750e2c4f7 100644 --- a/src/main/java/com/netgrif/application/engine/manager/web/body/request/LogoutRequest.java +++ b/src/main/java/com/netgrif/application/engine/manager/web/body/request/LogoutRequest.java @@ -8,6 +8,6 @@ @Data public class LogoutRequest { - private List<String> users; + private List<String> identities; } diff --git a/src/main/java/com/netgrif/application/engine/manager/web/body/response/AllLoggedUsersResponse.java b/src/main/java/com/netgrif/application/engine/manager/web/body/response/AllLoggedIdentitiesResponse.java similarity index 74% rename from src/main/java/com/netgrif/application/engine/manager/web/body/response/AllLoggedUsersResponse.java rename to src/main/java/com/netgrif/application/engine/manager/web/body/response/AllLoggedIdentitiesResponse.java index 52fd4a8cad7..11513bec140 100644 --- a/src/main/java/com/netgrif/application/engine/manager/web/body/response/AllLoggedUsersResponse.java +++ b/src/main/java/com/netgrif/application/engine/manager/web/body/response/AllLoggedIdentitiesResponse.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.manager.web.body.response; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.manager.web.SessionManagerController; import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; @@ -8,9 +8,9 @@ import java.util.Collection; -public class AllLoggedUsersResponse extends CollectionModel<LoggedUser> { +public class AllLoggedIdentitiesResponse extends CollectionModel<LoggedIdentity> { - public AllLoggedUsersResponse(Collection<LoggedUser> content) { + public AllLoggedIdentitiesResponse(Collection<LoggedIdentity> content) { super(content); buildLinks(); } diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/groups/NextGroupService.java b/src/main/java/com/netgrif/application/engine/orgstructure/groups/NextGroupService.java deleted file mode 100644 index 06cff1ebf5c..00000000000 --- a/src/main/java/com/netgrif/application/engine/orgstructure/groups/NextGroupService.java +++ /dev/null @@ -1,383 +0,0 @@ -package com.netgrif.application.engine.orgstructure.groups; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.RegisteredUser; -import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.auth.web.requestbodies.NewUserRequest; -import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; -import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; -import com.netgrif.application.engine.mail.interfaces.IMailAttemptService; -import com.netgrif.application.engine.mail.interfaces.IMailService; -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService; -import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField; -import com.netgrif.application.engine.petrinet.domain.dataset.MapOptionsField; -import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.security.service.ISecurityContextService; -import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.QCase; -import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; -import com.netgrif.application.engine.workflow.service.interfaces.IDataService; -import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; -import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; -import com.netgrif.application.engine.workflow.web.responsebodies.TaskDataSets; -import com.netgrif.application.engine.workflow.web.responsebodies.TaskReference; -import com.querydsl.core.BooleanBuilder; -import com.querydsl.core.types.Predicate; -import com.querydsl.core.types.dsl.BooleanExpression; -import freemarker.template.TemplateException; -import lombok.extern.slf4j.Slf4j; -import org.bson.types.ObjectId; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.i18n.LocaleContextHolder; -import org.springframework.data.domain.PageRequest; -import org.springframework.stereotype.Service; - -import javax.mail.MessagingException; -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; - -@Service -@Slf4j -public class NextGroupService implements INextGroupService { - - @Autowired - protected IWorkflowService workflowService; - - @Autowired - protected IMailService mailService; - - @Autowired - protected IMailAttemptService mailAttemptService; - - @Autowired - protected IUserService userService; - - @Autowired - protected IDataService dataService; - - @Autowired - protected IRegistrationService registrationService; - - @Autowired - protected IPetriNetService petriNetService; - - @Autowired - protected ITaskService taskService; - - @Autowired - protected IElasticCaseService elasticCaseService; - - @Autowired - protected ISecurityContextService securityContextService; - - - protected final static String GROUP_NET_IDENTIFIER = "org_group"; - protected final static String GROUP_INIT_TASK_ID = "2"; - - protected final static String GROUP_CASE_IDENTIFIER = "org_group"; - protected final static String GROUP_MEMBERS_FIELD = "members"; - protected final static String GROUP_AUTHOR_FIELD = "author"; - protected final static String GROUP_TITLE_FIELD = "group_name"; - - @Override - public CreateCaseEventOutcome createDefaultSystemGroup(IUser author) { - if (findDefaultGroup() != null) { - log.info("Default system group has already been created."); - return null; - } - return createGroup("Default system group", author); - } - - @Override - public CreateCaseEventOutcome createGroup(IUser author) { - return createGroup(author.getFullName(), author); - } - - @Override - public CreateCaseEventOutcome createGroup(String title, IUser author) { - Case userDefaultGroup = findUserDefaultGroup(author); - if (userDefaultGroup != null && userDefaultGroup.getTitle().equals(title)) { - return null; - } - PetriNet orgGroupNet = petriNetService.getNewestVersionByIdentifier(GROUP_NET_IDENTIFIER); - CreateCaseEventOutcome outcome = workflowService.createCase(orgGroupNet.getStringId(), title, "", author.transformToLoggedUser()); - - DataSet taskData = getInitialGroupData(author, title, outcome.getCase()); - Task initTask = getGroupInitTask(outcome.getCase()); - dataService.setData(initTask.getStringId(), taskData, author); - - try { - taskService.assignTask(author.transformToLoggedUser(), initTask.getStringId()); - taskService.finishTask(author.transformToLoggedUser(), initTask.getStringId()); - } catch (TransitionNotExecutableException e) { - log.error(e.getMessage()); - } - author.addGroup(outcome.getCase().getStringId()); - userService.save(author); - return outcome; - } - - @Override - public Case findGroup(String groupID) { - Case result = workflowService.searchOne(groupCase().and(QCase.case$.id.eq(new ObjectId(groupID)))); - if (!isGroupCase(result)) { - return null; - } - return result; - } - - @Override - public Case findDefaultGroup() { - return findByName("Default system group"); - } - - @Override - public Case findByName(String name) { - CaseSearchRequest request = new CaseSearchRequest(); - request.query = "title.keyword:\"" + name + "\""; - List<Case> result = elasticCaseService.search(Collections.singletonList(request), userService.getSystem().transformToLoggedUser(), PageRequest.of(0, 1), LocaleContextHolder.getLocale(), false).getContent(); - return !result.isEmpty() ? result.get(0) : null; - } - - @Override - public List<Case> findByPredicate(Predicate predicate) { - return workflowService.searchAll(predicate).getContent(); - } - - @Override - public List<Case> findByIds(Collection<String> groupIds) { - List<BooleanExpression> groupQueries = groupIds.stream().map(ObjectId::new).map(QCase.case$.id::eq).collect(Collectors.toList()); - BooleanBuilder builder = new BooleanBuilder(); - groupQueries.forEach(builder::or); - return this.workflowService.searchAll(groupCase().and(builder)).getContent(); - } - - @Override - public List<Case> findAllGroups() { - return workflowService.searchAll(groupCase()).getContent(); - } - - @Override - public Map<String, I18nString> inviteUser(String email, Map<String, I18nString> existingUsers, Case groupCase) { - if (!isGroupCase(groupCase)) { - return null; - } - IUser user = userService.findByEmail(email); - if (user != null && user.isActive()) { - log.info("User [{}] has already been registered.", user.getFullName()); - user.addGroup(groupCase.getStringId()); - userService.save(user); - return addUser(user, existingUsers); - } else { - log.info("Inviting new user to group."); - NewUserRequest newUserRequest = new NewUserRequest(); - newUserRequest.email = email; - RegisteredUser regUser = registrationService.createNewUser(newUserRequest); - regUser.addGroup(groupCase.getStringId()); - userService.save(regUser); - - try { - mailService.sendRegistrationEmail(regUser); - mailAttemptService.mailAttempt(newUserRequest.email); - } catch (MessagingException | IOException | TemplateException e) { - log.error(e.getMessage()); - } - return addUser(regUser, existingUsers); - } - } - - @Override - public void addUserToDefaultGroup(IUser user) { - addUser(user, findDefaultGroup()); - } - - @Override - public void addUser(IUser user, String groupId) { - Case groupCase = this.findGroup(groupId); - if (groupCase != null) { - this.addUser(user, groupCase); - } - } - - @Override - public void addUser(IUser user, Case groupCase) { - // TODO: release/8.0.0: WorkflowServiceTest#createCaseWithLocale - Cannot invoke "com.netgrif.application.engine.workflow.domain.Case.getDataField(String)" because "groupCase" is null - MapOptionsField<I18nString, String> field = (MapOptionsField<I18nString, String>) groupCase.getDataSet().get(GROUP_MEMBERS_FIELD); - Map<String, I18nString> existingUsers = field.getOptions(); - if (existingUsers == null) { - existingUsers = new HashMap<>(); - } - field.setOptions(addUser(user, existingUsers)); - workflowService.save(groupCase); - user.addGroup(groupCase.getStringId()); - userService.save(user); - securityContextService.saveToken(user.getStringId()); - } - - @Override - public Map<String, I18nString> addUser(IUser user, Map<String, I18nString> existingUsers) { - existingUsers.put(user.getStringId(), new I18nString(user.getEmail())); - return existingUsers; - } - - @Override - public void removeUser(IUser user, Case groupCase) { - HashSet<String> userIds = new HashSet<>(); - MapOptionsField<I18nString, String> field = (MapOptionsField<I18nString, String>) groupCase.getDataSet().get(GROUP_MEMBERS_FIELD); - Map<String, I18nString> existingUsers = field.getOptions(); - userIds.add(user.getStringId()); - field.setOptions(removeUser(userIds, existingUsers, groupCase)); - workflowService.save(groupCase); - } - - @Override - public Map<String, I18nString> removeUser(HashSet<String> usersToRemove, Map<String, I18nString> existingUsers, Case groupCase) { - String authorId = this.getGroupOwnerId(groupCase); - usersToRemove.forEach(user -> { - if (user.equals(authorId)) { - log.error("Author with id [{}] cannot be removed from group with ID [{}]", authorId, groupCase.getId().toString()); - } else { - existingUsers.remove(user); - securityContextService.saveToken(user); - } - }); - userService.findAllByIds(usersToRemove).forEach(user -> { - if (!user.getStringId().equals(authorId)) { - user.getNextGroups().remove(groupCase.getStringId()); - userService.save(user); - } - }); - return existingUsers; - } - - @Override - public Set<String> getAllCoMembers(IUser user) { -// TODO: release/8.0.0 -// Set<String> users = workflowService.searchAll( -// groupCase().and(QCase.case$.dataSet.get(GROUP_MEMBERS_FIELD).options.containsKey(user.getStringId()))) -// .map(it -> it.getDataSet().get(GROUP_MEMBERS_FIELD).getOptions().keySet()).stream() -// .collect(HashSet::new, Set::addAll, Set::addAll); -// users.remove(user.getStringId()); -// users.remove(userService.getSystem().getStringId()); -// return users; - return new HashSet<>(); - } - - - @Override - public List<IUser> getMembers(Case groupCase) { - if (!isGroupCase(groupCase)) { - return null; - } -// TODO: release/8.0.0 check field type is enummap - Set<String> userIds = ((EnumerationMapField)groupCase.getDataSet().get(GROUP_MEMBERS_FIELD)).getOptions().keySet(); - List<IUser> resultList = new ArrayList<>(); - userIds.forEach(id -> resultList.add(userService.resolveById(id))); - return resultList; - } - - @Override - public Set<String> getAllGroupsOfUser(IUser groupUser) { -// TODO: release/8.0.0 -// List<String> groupList = workflowService.searchAll(groupCase().and(QCase.case$.dataSet.get(GROUP_MEMBERS_FIELD).options.containsKey(groupUser.getStringId()))) -// .map(aCase -> aCase.getId().toString()).getContent(); -// return new HashSet<>(groupList); - return new HashSet<>(); - } - - @Override - public String getGroupOwnerId(String groupId) { - return this.getGroupOwnerId(this.findGroup(groupId)); - } - - @Override - public Collection<String> getGroupsOwnerIds(Collection<String> groupIds) { - return this.findByIds(groupIds).stream().map(this::getGroupOwnerId).collect(Collectors.toList()); - } - - @Override - public String getGroupOwnerEmail(String groupId) { - return this.getGroupOwnerEmail(this.findGroup(groupId)); - } - - @Override - public Collection<String> getGroupsOwnerEmails(Collection<String> groupIds) { - return this.findByIds(groupIds).stream().map(this::getGroupOwnerEmail).collect(Collectors.toList()); - } - - protected static BooleanExpression groupCase() { - return QCase.case$.processIdentifier.eq(GROUP_CASE_IDENTIFIER); - } - - protected boolean isGroupCase(Case aCase) { - if (aCase == null) { - log.error("The input case is a null object."); - return false; - } else if (!aCase.getProcessIdentifier().equals(GROUP_CASE_IDENTIFIER)) { - log.error("Case [{}] is not an organization group case.", aCase.getTitle()); - return false; - } - return true; - } - - protected boolean authorHasDefaultGroup(IUser author) { - List<Case> allGroups = findAllGroups(); - for (Case group : allGroups) { - if (group.getAuthor().getId().equals(author.getStringId())) { - return true; - } - } - return false; - } - - protected String getGroupOwnerId(Case groupCase) { - return groupCase.getAuthor().getId(); - } - - protected Case findUserDefaultGroup(IUser author) { - return workflowService.searchOne(QCase.case$.author.id.eq(author.getStringId()).and(QCase.case$.title.eq(author.getFullName()))); - } - - protected Task getGroupInitTask(Case groupCase) { - List<TaskReference> taskList = taskService.findAllByCase(groupCase.getStringId(), LocaleContextHolder.getLocale()); - Optional<TaskReference> initTaskReference = taskList.stream().filter(taskReference -> - taskReference.getTransitionId().equals(GROUP_INIT_TASK_ID)) - .findFirst(); - - if (initTaskReference.isEmpty()) { - log.error("Initial task of group case is not present!"); - return null; - } - - String initTaskId = initTaskReference.get().getStringId(); - return taskService.findById(initTaskId); - } - - protected DataSet getInitialGroupData(IUser author, String title, Case groupCase) { - DataSet dataSet = new DataSet(); - -// TODO: release/8.0.0 -// groupCase.getDataSet().get(GROUP_MEMBERS_FIELD).setOptions(addUser(author, new HashMap<>())); -// workflowService.save(groupCase); -// -// DataField authorData = new DataField(); -// authorData.setValue(author.getStringId()); -// DataField titleData = new DataField(); -// titleData.setValue(title); -// -// dataSet.getFields().put(GROUP_TITLE_FIELD, titleData); -// dataSet.getFields().put(GROUP_AUTHOR_FIELD, authorData); - return dataSet; - } - - protected String getGroupOwnerEmail(Case groupCase) { - return groupCase.getAuthor().getEmail(); - } -} diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/groups/config/GroupConfigurationProperties.java b/src/main/java/com/netgrif/application/engine/orgstructure/groups/config/GroupConfigurationProperties.java deleted file mode 100644 index eec6ffbcfd9..00000000000 --- a/src/main/java/com/netgrif/application/engine/orgstructure/groups/config/GroupConfigurationProperties.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.netgrif.application.engine.orgstructure.groups.config; - -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -@Slf4j -@Data -@Component -@ConfigurationProperties(prefix = "nae.group") -public class GroupConfigurationProperties { - - /** - * Determines whether user's default groups are enabled and can be created - */ - private boolean defaultEnabled = true; - - /** - * Determines whether default system group is enabled and can be created - */ - private boolean systemEnabled = true; -} diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/groups/interfaces/INextGroupService.java b/src/main/java/com/netgrif/application/engine/orgstructure/groups/interfaces/INextGroupService.java deleted file mode 100644 index 448d79ba1dc..00000000000 --- a/src/main/java/com/netgrif/application/engine/orgstructure/groups/interfaces/INextGroupService.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.netgrif.application.engine.orgstructure.groups.interfaces; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; -import com.querydsl.core.types.Predicate; - -import java.util.*; - -public interface INextGroupService { - - CreateCaseEventOutcome createDefaultSystemGroup(IUser author); - - CreateCaseEventOutcome createGroup(IUser author); - - CreateCaseEventOutcome createGroup(String title, IUser author); - - Case findGroup(String groupID); - - List<Case> findByIds(Collection<String> groupIds); - - List<Case> findAllGroups(); - - Case findDefaultGroup(); - - Case findByName(String name); - - List<Case> findByPredicate(Predicate predicate); - - Map<String, I18nString> inviteUser(String email, Map<String, I18nString> existingUsers, Case groupCase); - - void addUserToDefaultGroup(IUser user); - - void addUser(IUser user, String groupCase); - - void addUser(IUser user, Case groupCase); - - Map<String, I18nString> addUser(IUser user, Map<String, I18nString> existingUsers); - - void removeUser(IUser user, Case groupCase); - - Map<String, I18nString> removeUser(HashSet<String> usersToRemove, Map<String, I18nString> existingUsers, Case groupCase); - - List<IUser> getMembers(Case groupCase); - - Set<String> getAllGroupsOfUser(IUser groupUser); - - String getGroupOwnerId(String groupId); - - Collection<String> getGroupsOwnerIds(Collection<String> groupIds); - - String getGroupOwnerEmail(String groupId); - - Collection<String> getGroupsOwnerEmails(Collection<String> groupIds); - - Set<String> getAllCoMembers(IUser user); - -} diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java deleted file mode 100644 index fe71caf115c..00000000000 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.netgrif.application.engine.orgstructure.web; - -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService; -import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; -import com.netgrif.application.engine.orgstructure.web.responsebodies.GroupsResource; -import com.netgrif.application.engine.workflow.domain.Case; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.hateoas.MediaTypes; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -@RestController -@RequestMapping("/api/group") -@ConditionalOnProperty( - value = "nae.group.web.enabled", - havingValue = "true", - matchIfMissing = true -) -@Tag(name = "Group") -public class GroupController { - - private final INextGroupService service; - - public GroupController(INextGroupService service) { - this.service = service; - } - - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") - @Operation(summary = "Get all groups in the system", - description = "Caller must have the ADMIN role", - security = {@SecurityRequirement(name = "BasicAuth")}) - @GetMapping(value = "/all", produces = MediaTypes.HAL_JSON_VALUE) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK"), - @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), - }) - public GroupsResource getAllGroups() { - List<Case> groups = service.findAllGroups(); - Set<Group> groupResponse = groups.stream() - .map(aCase -> new Group(aCase.getStringId(), aCase.getTitle())) - .collect(Collectors.toCollection(HashSet::new)); - return new GroupsResource(groupResponse); - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/LdapController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/LdapController.java index 9181d391b0c..d70be80d0aa 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/LdapController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/LdapController.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.orgstructure.web; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.ldap.domain.LdapGroup; import com.netgrif.application.engine.ldap.domain.LdapGroupRef; import com.netgrif.application.engine.ldap.service.interfaces.ILdapGroupRefService; @@ -8,15 +8,15 @@ import com.netgrif.application.engine.orgstructure.web.requestbodies.LdapGroupSearchBody; import com.netgrif.application.engine.orgstructure.web.responsebodies.LdapGroupResponseBody; import com.netgrif.application.engine.orgstructure.web.responsebodies.LdapGroupsResource; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; +import com.netgrif.application.engine.authorization.domain.ProcessRole; import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; @@ -35,15 +35,15 @@ @Slf4j @RestController +@Tag(name = "Ldap") +@RequiredArgsConstructor @RequestMapping("/api/ldap") @ConditionalOnExpression("${nae.ldap.enabled:false}") -@Tag(name = "Ldap") public class LdapController { - @Autowired - protected ILdapGroupRefService service; + protected final ILdapGroupRefService service; - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") @Operation(summary = "Get all ldap groups", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -54,7 +54,7 @@ public class LdapController { }) public LdapGroupsResource getAllLdapGroups(@RequestBody LdapGroupSearchBody body, Authentication auth) { List<LdapGroupRef> groups; - if (body == null || body.getFulltext().equals("")) { + if (body == null || body.getFulltext().isEmpty()) { groups = service.findAllGroups(); } else { groups = service.searchGroups(body.getFulltext()); @@ -62,14 +62,17 @@ public LdapGroupsResource getAllLdapGroups(@RequestBody LdapGroupSearchBody body List<LdapGroup> groupRoles = service.getAllLdapGroupRoles(); Set<LdapGroupResponseBody> ldapGroupResponse = groups.stream() .map(group -> { - Set<ProcessRole> processRoleSet = groupRoles.stream().filter(ldapGroup -> ldapGroup.getDn().equals(group.getDn().toString())).map(LdapGroup::getProcessesRoles).flatMap(Collection::stream).collect(Collectors.toSet()); + Set<ProcessRole> processRoleSet = groupRoles.stream() + .filter(ldapGroup -> ldapGroup.getDn().equals(group.getDn().toString())) + .map(LdapGroup::getProcessesProcessRoles).flatMap(Collection::stream) + .collect(Collectors.toSet()); return new LdapGroupResponseBody(group.getDn().toString(), group.getCn(), group.getDescription(), processRoleSet); }) .collect(Collectors.toCollection(HashSet::new)); return new LdapGroupsResource(ldapGroupResponse); } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") @Operation(summary = "Assign role to the ldap group", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -80,8 +83,8 @@ public LdapGroupsResource getAllLdapGroups(@RequestBody LdapGroupSearchBody body }) public MessageResource assignRolesToLdapGroup(@RequestBody LdapGroupRoleAssignRequestBody requestBody, Authentication auth) { try { - service.setRoleToLdapGroup(requestBody.getGroupDn(), requestBody.getRoleIds(), (LoggedUser) auth.getPrincipal()); - log.info("Process roles " + requestBody.getRoleIds() + " assigned to group " + requestBody.getGroupDn()); + service.setRoleToLdapGroup(requestBody.getGroupDn(), requestBody.getRoleIds(), (LoggedIdentity) auth.getPrincipal()); + log.info("Process roles {} assigned to group {}", requestBody.getRoleIds(), requestBody.getGroupDn()); return MessageResource.successMessage("Selected roles assigned to group " + requestBody.getGroupDn()); } catch (IllegalArgumentException e) { log.error(e.getMessage()); diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/Group.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/Group.java deleted file mode 100644 index 2d47b50145c..00000000000 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/Group.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.netgrif.application.engine.orgstructure.web.responsebodies; - -import lombok.Data; - -@Data -public class Group { - - private String id; - private String name; - - public Group(String id, String name) { - this.id = id; - this.name = name; - } -} diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/GroupsResource.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/GroupsResource.java deleted file mode 100644 index a6039cd6bde..00000000000 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/GroupsResource.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.netgrif.application.engine.orgstructure.web.responsebodies; - -import com.netgrif.application.engine.orgstructure.web.GroupController; -import org.springframework.hateoas.CollectionModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; - - -public class GroupsResource extends CollectionModel<Group> { - - public GroupsResource(Iterable<Group> content) { - super(content); - buildLinks(); - } - - private void buildLinks() { - add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(GroupController.class) - .getAllGroups()).withSelfRel()); - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/LdapGroupResponseBody.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/LdapGroupResponseBody.java index 40fba756388..e17857ec242 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/LdapGroupResponseBody.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/LdapGroupResponseBody.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.orgstructure.web.responsebodies; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; +import com.netgrif.application.engine.authorization.domain.ProcessRole; import lombok.AllArgsConstructor; import lombok.Data; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/Component.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/Component.java index c63b9c9529f..8d9afa73691 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/Component.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/Component.java @@ -1,55 +1,31 @@ package com.netgrif.application.engine.petrinet.domain; -import lombok.Getter; -import lombok.Setter; +import com.netgrif.application.engine.utils.UniqueKeyMapWrapper; +import lombok.AllArgsConstructor; +import lombok.Data; import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; +@Data +@AllArgsConstructor public class Component implements Serializable { private static final long serialVersionUID = 5852012111111766631L; - public static final String DIVIDER = "divider"; - - @Getter - @Setter - private String name; - - @Getter - @Setter - private Map<String, String> properties; - - @Getter - @Setter - private List<Icon> optionIcons; + private String id; + private UniqueKeyMapWrapper<String> properties; public Component() { + this.properties = new UniqueKeyMapWrapper<>(); } - public Component(String name) { - this.name = name; - this.properties = new HashMap<>(); - this.optionIcons = new ArrayList<>(); - } - - public Component(String name, Map<String, String> properties) { - this(name); - this.properties = properties; - } - - public Component(String name, Map<String, String> properties, List<Icon> optionIcons) { - this(name); - this.properties = properties; - this.optionIcons = optionIcons; + public Component(String id) { + this(); + this.id = id; } @Override public Component clone() { - return new Component(this.name, new HashMap<>(this.properties), this.optionIcons == null ? new ArrayList<>() : this.optionIcons.stream().map(Icon::clone).collect(Collectors.toList())); + return new Component(this.id, new UniqueKeyMapWrapper<>(this.properties)); } } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/DataGroup.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/DataGroup.java deleted file mode 100644 index 69c52efccc1..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/DataGroup.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.netgrif.application.engine.importer.model.DataGroupAlignment; -import com.netgrif.application.engine.petrinet.domain.layout.DataGroupLayout; -import com.querydsl.core.annotations.PropertyType; -import com.querydsl.core.annotations.QueryType; -import lombok.Data; -import org.bson.types.ObjectId; -import org.springframework.data.annotation.Transient; -import org.springframework.data.mongodb.core.mapping.Document; - -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Set; - -@Data -@Document -public class DataGroup extends PetriNetObject { - - @JsonIgnore - private Set<String> data; - - @Transient - private LinkedHashMap<String, DataRef> dataRefs; - - @QueryType(PropertyType.NONE) - private DataGroupLayout layout; - - private I18nString title; - - @QueryType(PropertyType.NONE) - private DataGroupAlignment alignment; - - private Boolean stretch; - - @Transient - private String parentTaskId; - - @Transient - private String parentTransitionId; - - @Transient - private String parentCaseId; - - @Transient - private String parentTaskRefId; - - @Transient - private int nestingLevel; - - public DataGroup() { - this.id = new ObjectId(); - this.data = new LinkedHashSet<>(); - } - - public void addData(String dataId) { - data.add(dataId); - } - - public DataGroup clone() { - DataGroup group = new DataGroup(); - group.setImportId(this.getImportId()); - group.setTitle(this.getTitle()); - group.setData(this.getData()); - group.setLayout(this.getLayout()); - group.setAlignment(this.getAlignment()); - group.setStretch(this.getStretch()); - return group; - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/DataGroupAlignmentConverter.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/DataGroupAlignmentConverter.java deleted file mode 100644 index 23d60203bef..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/DataGroupAlignmentConverter.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain; - -import com.netgrif.application.engine.importer.model.DataGroupAlignment; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.convert.converter.Converter; -import org.springframework.data.convert.ReadingConverter; -import org.springframework.stereotype.Component; - -@Slf4j -@Component -@ReadingConverter -public class DataGroupAlignmentConverter implements Converter<String, DataGroupAlignment> { - - @Override - public DataGroupAlignment convert(String source) { - if (source.isBlank()) { - return null; - } - return DataGroupAlignment.fromValue(source.toLowerCase()); - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/DataRef.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/DataRef.java index 9df142f6bd5..3efc2f77ea7 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/DataRef.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/DataRef.java @@ -4,7 +4,6 @@ import com.netgrif.application.engine.importer.model.DataEventType; import com.netgrif.application.engine.petrinet.domain.dataset.Field; import com.netgrif.application.engine.petrinet.domain.dataset.logic.FieldBehavior; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.FieldLayout; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; import com.netgrif.application.engine.petrinet.domain.events.DataEvent; import com.netgrif.application.engine.petrinet.domain.events.EventPhase; @@ -13,6 +12,7 @@ import lombok.NoArgsConstructor; import org.springframework.data.annotation.Transient; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -20,7 +20,6 @@ @Data -@NoArgsConstructor public class DataRef { private String fieldId; @@ -29,15 +28,20 @@ public class DataRef { @Transient private DataFieldBehavior behavior; private Map<DataEventType, DataEvent> events; - private FieldLayout layout; private Component component; - @Transient - protected String parentTaskId; - @Transient - protected String parentCaseId; + // TODO: release/8.0.0 parentCaseId + // TODO: release/8.0.0 uniqeue key map + private Map<String, String> properties; + + public DataRef() { + this.events = new HashMap<>(); + this.properties = new HashMap<>(); + } public DataRef(Field<?> field, DataFieldBehavior behavior) { + this(); this.field = field; + this.fieldId = field.getImportId(); this.setBehavior(behavior); } @@ -63,6 +67,10 @@ public static List<Action> getEventAction(DataEvent event, EventPhase phase) { } } + public void addEvent(DataEvent event) { + events.put(event.getType(), event); + } + @Override public String toString() { return fieldId; @@ -94,7 +102,11 @@ private boolean isBehaviorSet(FieldBehavior behavior) { public DataRef clone() { DataRef cloned = new DataRef(); - // TODO: release/8.0.0 implement + cloned.setFieldId(this.fieldId); + cloned.setField(this.field == null ? null : this.field.clone()); + cloned.setBehavior(this.behavior == null ? null : this.behavior.clone()); + cloned.setEvents(this.events == null || this.events.isEmpty() ? new HashMap<>() : new HashMap<>(this.events)); + cloned.setComponent(this.component == null ? null : this.component.clone()); return cloned; } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/Function.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/Function.java index e4b678830c5..bc749020cca 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/Function.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/Function.java @@ -7,7 +7,7 @@ import org.springframework.data.mongodb.core.mapping.Document; @Document -public class Function extends PetriNetObject { +public class Function extends ProcessObject { @Getter @Setter diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/I18nExpression.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/I18nExpression.java new file mode 100644 index 00000000000..f88c10b8364 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/I18nExpression.java @@ -0,0 +1,38 @@ +package com.netgrif.application.engine.petrinet.domain; + +import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.HashMap; +import java.util.Locale; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class I18nExpression extends I18nString { + private boolean dynamic; + + public I18nExpression(String defaultValue) { + super(defaultValue); + this.dynamic = false; + } + + public I18nExpression clone() { + I18nExpression clone = new I18nExpression(); + clone.setKey(this.getKey()); + clone.setDefaultValue(this.getDefaultValue()); + clone.setTranslations(new HashMap<>(this.getTranslations())); + clone.setDynamic(this.dynamic); + return clone; + } + + public Expression<String> getExpression(Locale locale) { + String translation = this.getTranslation(locale); + if (this.dynamic) { + return Expression.ofDynamic(translation); + } + return Expression.ofStatic(translation); + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/I18nString.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/I18nString.java index 784e8d1ce47..03ce44cee04 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/I18nString.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/I18nString.java @@ -53,8 +53,9 @@ public String getTranslation(String locale) { } public String getTranslation(Locale locale) { - if (locale == null) + if (locale == null) { return defaultValue; + } return getTranslation(locale.getLanguage()); } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/Imported.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/Imported.java index 2c9515cb776..4149b592f5e 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/Imported.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/Imported.java @@ -1,18 +1,13 @@ package com.netgrif.application.engine.petrinet.domain; +import lombok.Data; + import java.io.Serializable; +@Data public abstract class Imported implements Serializable { private static final long serialVersionUID = -2708949961379974800L; protected String importId; - - public String getImportId() { - return importId; - } - - public void setImportId(String id) { - this.importId = id; - } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/Node.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/Node.java index da0091a6ecd..0d3c3996422 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/Node.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/Node.java @@ -1,48 +1,20 @@ package com.netgrif.application.engine.petrinet.domain; -import lombok.Getter; -import org.bson.types.ObjectId; +import com.netgrif.application.engine.utils.UniqueKeyMapWrapper; +import lombok.*; import org.springframework.data.mongodb.core.mapping.Document; +@EqualsAndHashCode(callSuper = true) @Document -public abstract class Node extends PetriNetObject { +@Data +@AllArgsConstructor +public abstract class Node extends ProcessObject { - @Getter - private Position position; - - @Getter private I18nString title; + private UniqueKeyMapWrapper<String> properties; public Node() { - this.setObjectId(new ObjectId()); - position = new Position(); - } - - public void setPositionX(int x) { - position.setX(x); - } - - public void setPositionY(int y) { - position.setY(y); - } - - public void setPosition(int x, int y) { - position.setX(x); - position.setY(y); - } - - public void setPosition(Position positionData) { - if (positionData != null) { - position.setY(positionData.getY()); - position.setX(positionData.getX()); - } - } - - public void setTitle(I18nString title) { - this.title = title; - } - - public void setTitle(String title) { - setTitle(new I18nString(title)); + super(); + this.properties = new UniqueKeyMapWrapper<>(); } } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNet.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNet.java deleted file mode 100644 index 0c97c3c2668..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNet.java +++ /dev/null @@ -1,441 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain; - -import com.netgrif.application.engine.auth.domain.Author; -import com.netgrif.application.engine.importer.model.CaseEventType; -import com.netgrif.application.engine.importer.model.ProcessEventType; -import com.netgrif.application.engine.petrinet.domain.arcs.Arc; -import com.netgrif.application.engine.petrinet.domain.arcs.reference.Referencable; -import com.netgrif.application.engine.petrinet.domain.arcs.reference.Type; -import com.netgrif.application.engine.petrinet.domain.dataset.Field; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; -import com.netgrif.application.engine.petrinet.domain.events.CaseEvent; -import com.netgrif.application.engine.petrinet.domain.events.ProcessEvent; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission; -import com.netgrif.application.engine.petrinet.domain.version.Version; -import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; -import lombok.Getter; -import lombok.Setter; -import org.bson.types.ObjectId; -import org.springframework.data.mongodb.core.mapping.DBRef; -import org.springframework.data.mongodb.core.mapping.Document; - -import java.time.LocalDateTime; -import java.util.*; -import java.util.stream.Collectors; - -@Document -public class PetriNet extends PetriNetObject { - - - @Getter - @Setter - private String identifier; //combination of identifier and version must be unique ... maybe use @CompoundIndex? - - @Getter - @Setter - private String uriNodeId; - - @Getter - private I18nString title; - - @Getter - @Setter - private boolean defaultRoleEnabled; - - @Getter - @Setter - private boolean anonymousRoleEnabled; - - @Getter - @Setter - private I18nString defaultCaseName; - - @Getter - @Setter - private Expression defaultCaseNameExpression; - - @Getter - @Setter - private String initials; - - @Getter - @Setter - private String icon; - - // TODO: 18. 3. 2017 replace with Spring auditing - @Getter - @Setter - private LocalDateTime creationDate; - - @Getter - @Setter - private Version version; - - @Getter - @Setter - private Author author; - - @org.springframework.data.mongodb.core.mapping.Field("places") - @Getter - @Setter - private LinkedHashMap<String, Place> places; - - @org.springframework.data.mongodb.core.mapping.Field("transitions") - @Getter - @Setter - private LinkedHashMap<String, Transition> transitions; - - @org.springframework.data.mongodb.core.mapping.Field("arcs") - @Getter - @Setter - // TODO: release/8.0.0 save sorted by execution priority - private LinkedHashMap<String, List<Arc>> arcs;//todo: import id - - @org.springframework.data.mongodb.core.mapping.Field("dataset") - @Getter - @Setter - private LinkedHashMap<String, Field<?>> dataSet; - - @org.springframework.data.mongodb.core.mapping.Field("roles") - @DBRef - @Getter - @Setter - private LinkedHashMap<String, ProcessRole> roles; - - @org.springframework.data.mongodb.core.mapping.Field("transactions") - @Getter - @Setter - private LinkedHashMap<String, Transaction> transactions;//todo: import id - - @Getter - @Setter - private Map<ProcessEventType, ProcessEvent> processEvents; - - @Getter - @Setter - private Map<CaseEventType, CaseEvent> caseEvents; - - @Getter - @Setter - private Map<String, Map<ProcessRolePermission, Boolean>> permissions; - - @Getter - @Setter - private List<String> negativeViewRoles; - - @Getter - @Setter - private Map<String, Map<ProcessRolePermission, Boolean>> userRefs; - - @Getter - @Setter - private List<Function> functions; - - @Getter - @Setter - private String importXmlPath; - - @Getter - @Setter - private Map<String, String> tags; - - public PetriNet() { - this.id = new ObjectId(); - this.identifier = "Default"; - this.initials = ""; - this.title = new I18nString(""); - this.importId = ""; - this.version = new Version(); - defaultCaseName = new I18nString(""); - creationDate = LocalDateTime.now(); - places = new LinkedHashMap<>(); - transitions = new LinkedHashMap<>(); - arcs = new LinkedHashMap<>(); - dataSet = new LinkedHashMap<>(); - roles = new LinkedHashMap<>(); - negativeViewRoles = new LinkedList<>(); - transactions = new LinkedHashMap<>(); - processEvents = new LinkedHashMap<>(); - caseEvents = new LinkedHashMap<>(); - permissions = new HashMap<>(); - userRefs = new HashMap<>(); - functions = new LinkedList<>(); - tags = new HashMap<>(); - } - - public void addPlace(Place place) { - this.places.put(place.getStringId(), place); - } - - public void addTransition(Transition transition) { - this.transitions.put(transition.getStringId(), transition); - } - - public void addRole(ProcessRole role) { - this.roles.put(role.getStringId(), role); - } - - public void addPermission(String roleId, Map<ProcessRolePermission, Boolean> permissions) { - if (this.permissions.containsKey(roleId) && this.permissions.get(roleId) != null) { - this.permissions.get(roleId).putAll(permissions); - } else { - this.permissions.put(roleId, permissions); - } - } - - public void addNegativeViewRole(String roleId) { - negativeViewRoles.add(roleId); - } - - public void addFunction(Function function) { - functions.add(function); - } - - public void addUserPermission(String usersRefId, Map<ProcessRolePermission, Boolean> permissions) { - if (this.userRefs.containsKey(usersRefId) && this.userRefs.get(usersRefId) != null) { - this.userRefs.get(usersRefId).putAll(permissions); - } else { - this.userRefs.put(usersRefId, permissions); - } - } - - public List<Arc> getArcsOfTransition(Transition transition) { - return getArcsOfTransition(transition.getStringId()); - } - - public List<Arc> getArcsOfTransition(String transitionId) { - if (arcs.containsKey(transitionId)) { - return arcs.get(transitionId); - } - return new LinkedList<>(); - } - - public void addDataSetField(Field<?> field) { - this.dataSet.put(field.getStringId(), field); - } - - public void addArc(Arc arc) { - String transitionId = arc.getTransition().getStringId(); - if (arcs.containsKey(transitionId)) { - arcs.get(transitionId).add(arc); - } else { - List<Arc> arcList = new LinkedList<>(); - arcList.add(arc); - arcs.put(transitionId, arcList); - } - } - - public Node getNode(String importId) { - if (places.containsKey(importId)) { - return getPlace(importId); - } - if (transitions.containsKey(importId)) { - return getTransition(importId); - } - return null; - } - - public Optional<Field<?>> getField(String id) { - return Optional.ofNullable(dataSet.get(id)); - } - - public Place getPlace(String id) { - return places.get(id); - } - - public Transition getTransition(String id) { - if ("fake".equals(id)) { - return new Transition(); - } - return transitions.get(id); - } - - public void initializeArcs() { - arcs.values().forEach(list -> list.forEach(arc -> { - arc.setSource(getNode(arc.getSourceId())); - arc.setDestination(getNode(arc.getDestinationId())); - })); - } - - public void initializeTokens(Map<String, Integer> activePlaces) { - places.values().forEach(place -> place.setTokens(activePlaces.getOrDefault(place.getStringId(), 0))); - } - - public void initializeArcs(DataSet dataSet) { - arcs.values() - .stream() - .flatMap(List::stream) - .filter(arc -> arc.getReference() != null) - .forEach(arc -> { - String referenceId = arc.getReference().getReference(); - arc.getReference().setReferencable(getArcReference(referenceId, arc.getReference().getType(), dataSet)); - }); - } - - private Referencable getArcReference(String referenceId, Type type, DataSet dataSet) { - if (type == Type.PLACE) { - return places.get(referenceId); - } else { - // TODO: release/8.0.0 check if number field? - return (Referencable) dataSet.get(referenceId); - } - } - - public Map<String, Integer> getActivePlaces() { - return places.values().stream() - .filter(Place::hasAnyTokens) - .collect(Collectors.toMap(PetriNetObject::getStringId, Place::getTokens)); - } - - public void addTransaction(Transaction transaction) { - this.transactions.put(transaction.getStringId(), transaction); - } - - public Transaction getTransactionByTransition(Transition transition) { - return transactions.values().stream() - .filter(transaction -> - transaction.getTransitions().contains(transition.getStringId()) - ) - .findAny() - .orElse(null); - } - - public List<Field<?>> getImmediateFields() { - return this.dataSet.values().stream().filter(Field::isImmediate).collect(Collectors.toList()); - } - - public void incrementVersion(VersionType type) { - this.version.increment(type); - } - - @Override - public String toString() { - return title.toString(); - } - - public void setTitle(I18nString title) { - this.title = title; - } - - public void setTitle(String title) { - setTitle(new I18nString(title)); - } - - public String getTranslatedDefaultCaseName(Locale locale) { - if (defaultCaseName == null) { - return ""; - } - return defaultCaseName.getTranslation(locale); - } - - public List<Function> getFunctions(FunctionScope scope) { - return functions.stream().filter(function -> function.getScope().equals(scope)).collect(Collectors.toList()); - } - - public List<Action> getPreCreateActions() { - return getPreCaseActions(CaseEventType.CREATE); - } - - public List<Action> getPostCreateActions() { - return getPostCaseActions(CaseEventType.CREATE); - } - - public List<Action> getPreDeleteActions() { - return getPreCaseActions(CaseEventType.DELETE); - } - - public List<Action> getPostDeleteActions() { - return getPostCaseActions(CaseEventType.DELETE); - } - - public List<Action> getPreUploadActions() { - return getPreProcessActions(ProcessEventType.UPLOAD); - } - - public List<Action> getPostUploadActions() { - return getPostProcessActions(ProcessEventType.UPLOAD); - } - - private List<Action> getPreCaseActions(CaseEventType type) { - if (caseEvents.containsKey(type)) { - return caseEvents.get(type).getPreActions(); - } - return new LinkedList<>(); - } - - private List<Action> getPostCaseActions(CaseEventType type) { - if (caseEvents.containsKey(type)) { - return caseEvents.get(type).getPostActions(); - } - return new LinkedList<>(); - } - - private List<Action> getPreProcessActions(ProcessEventType type) { - if (processEvents.containsKey(type)) { - return processEvents.get(type).getPreActions(); - } - return new LinkedList<>(); - } - - private List<Action> getPostProcessActions(ProcessEventType type) { - if (processEvents.containsKey(type)) { - return processEvents.get(type).getPostActions(); - } - return new LinkedList<>(); - } - - public boolean hasDynamicCaseName() { - return defaultCaseNameExpression != null; - } - - @Override - public String getStringId() { - return id.toString(); - } - - public PetriNet clone() { - PetriNet clone = new PetriNet(); - clone.setIdentifier(this.identifier); - clone.setUriNodeId(this.uriNodeId); - clone.setInitials(this.initials); - clone.setTitle(this.title.clone()); - clone.setDefaultRoleEnabled(this.defaultRoleEnabled); - clone.setDefaultCaseName(this.defaultCaseName == null ? null : this.defaultCaseName.clone()); - clone.setDefaultCaseNameExpression(this.defaultCaseNameExpression == null ? null : this.defaultCaseNameExpression.clone()); - clone.setIcon(this.icon); - clone.setCreationDate(this.creationDate); - clone.setVersion(this.version == null ? null : this.version.clone()); - clone.setAuthor(this.author == null ? null : this.author.clone()); - clone.setTransitions(this.transitions == null ? null : this.transitions.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone(), (v1, v2) -> v1, LinkedHashMap::new))); - clone.setRoles(this.roles == null ? null : this.roles.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone(), (v1, v2) -> v1, LinkedHashMap::new))); - clone.setTransactions(this.transactions == null ? null : this.transactions.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone(), (v1, v2) -> v1, LinkedHashMap::new))); - clone.setImportXmlPath(this.importXmlPath); - clone.setImportId(this.importId); - clone.setObjectId(this.id); - clone.setDataSet(this.dataSet.entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone(), (x, y) -> y, LinkedHashMap::new)) - ); - clone.setPlaces(this.places.entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone(), (x, y) -> y, LinkedHashMap::new)) - ); - clone.setArcs(this.arcs.entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream() - .map(Arc::clone) - .collect(Collectors.toList()), (x, y) -> y, LinkedHashMap::new)) - ); - clone.initializeArcs(); - clone.setCaseEvents(this.caseEvents == null ? null : this.caseEvents.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone()))); - clone.setProcessEvents(this.processEvents == null ? null : this.processEvents.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone()))); - clone.setPermissions(this.permissions == null ? null : this.permissions.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new HashMap<>(e.getValue())))); - clone.setUserRefs(this.userRefs == null ? null : this.userRefs.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new HashMap<>(e.getValue())))); - this.getNegativeViewRoles().forEach(clone::addNegativeViewRole); - this.getFunctions().forEach(clone::addFunction); - clone.setTags(new HashMap<>(this.tags)); - return clone; - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNetIdentifier.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNetIdentifier.java new file mode 100644 index 00000000000..4d5d8e56f04 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNetIdentifier.java @@ -0,0 +1,42 @@ +package com.netgrif.application.engine.petrinet.domain; + +import com.netgrif.application.engine.petrinet.domain.version.Version; +import lombok.Getter; +import lombok.Setter; +import org.bson.types.ObjectId; +import org.springframework.data.mongodb.core.index.CompoundIndex; +import org.springframework.data.mongodb.core.index.Indexed; + +@Getter +@Setter +@CompoundIndex(name = "cmp-idx-one", def = "{'identifier': 1, 'version.major': -1, 'version.minor': -1, 'version.patch': -1}") +public class PetriNetIdentifier { + + private ObjectId id; + + @Indexed + private String identifier; + + private Version version; + + public PetriNetIdentifier() { + identifier = "Default"; + version = new Version(); + this.id = new ObjectId(); + } + + public PetriNetIdentifier(String identifier, Version version, ObjectId id) { + this.identifier = identifier; + this.version = version; + this.id = id; + } + + @Override + public PetriNetIdentifier clone() { + PetriNetIdentifier clone = new PetriNetIdentifier(); + clone.setIdentifier(identifier); + clone.setVersion(version == null ? null : version.clone()); + clone.setId(id); + return clone; + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNetSearch.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNetSearch.java index e7a0433a567..7bcb19ec4e0 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNetSearch.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNetSearch.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.petrinet.domain; -import com.netgrif.application.engine.auth.domain.Author; +import com.netgrif.application.engine.authorization.domain.Actor; import com.netgrif.application.engine.petrinet.domain.version.Version; import lombok.Getter; import lombok.Setter; @@ -22,13 +22,11 @@ public class PetriNetSearch { private String initials; - private List<String> group; - private Version version; - private Author author; + private Actor author; - private List<String> negativeViewRoles; + private List<String> negativeViewProcessRoles; private Map<String, String> tags; } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/Place.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/Place.java index fd02f0e283a..d4b682cef4e 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/Place.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/Place.java @@ -1,32 +1,27 @@ package com.netgrif.application.engine.petrinet.domain; -import com.netgrif.application.engine.petrinet.domain.arcs.reference.Referencable; -import lombok.Getter; -import lombok.Setter; +import com.netgrif.application.engine.petrinet.domain.throwable.IllegalMarkingException; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import org.springframework.data.mongodb.core.mapping.Document; +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor @Document -public class Place extends Node implements Referencable { +public class Place extends Node { - @Getter - @Setter - private Integer tokens; + private int tokens; - @Getter - @Setter - private Boolean isStatic; - - public Place() { - super(); - } public void addTokens(int tokens) { this.tokens += tokens; } - public void removeTokens(Integer tokens) throws IllegalArgumentException { + public void removeTokens(int tokens) throws IllegalArgumentException { if (this.tokens - tokens < 0) { - throw new IllegalArgumentException("Place can not have negative number of tokens."); + throw new IllegalMarkingException(this); } this.tokens -= tokens; } @@ -47,16 +42,8 @@ public String toString() { public Place clone() { Place clone = new Place(); clone.setTokens(this.tokens); - clone.setIsStatic(this.isStatic); clone.setTitle(this.getTitle()); - clone.setPosition(this.getPosition()); - clone.setObjectId(this.getObjectId()); clone.setImportId(this.getImportId()); return clone; } - - @Override - public int getMultiplicity() { - return tokens; - } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/Process.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/Process.java new file mode 100644 index 00000000000..59476ce117e --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/Process.java @@ -0,0 +1,313 @@ +package com.netgrif.application.engine.petrinet.domain; + +import com.netgrif.application.engine.authorization.domain.permissions.AccessPermissions; +import com.netgrif.application.engine.importer.model.CaseEventType; +import com.netgrif.application.engine.importer.model.ProcessEventType; +import com.netgrif.application.engine.petrinet.domain.arcs.Arc; +import com.netgrif.application.engine.petrinet.domain.arcs.ArcCollection; +import com.netgrif.application.engine.petrinet.domain.arcs.PTArc; +import com.netgrif.application.engine.petrinet.domain.arcs.TPArc; +import com.netgrif.application.engine.petrinet.domain.dataset.Field; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; +import com.netgrif.application.engine.petrinet.domain.events.CaseEvent; +import com.netgrif.application.engine.petrinet.domain.events.ProcessEvent; +import com.netgrif.application.engine.authorization.domain.permissions.CasePermission; +import com.netgrif.application.engine.petrinet.domain.version.Version; +import com.netgrif.application.engine.utils.UniqueKeyMapWrapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.bson.types.ObjectId; +import org.springframework.data.mongodb.core.index.CompoundIndex; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +@Data +@Document +@EqualsAndHashCode(callSuper = true) +@CompoundIndex(name = "cmp-idx-one", def = "{'identifier': 1, 'version.major': -1, 'version.minor': -1, 'version.patch': -1}") +public class Process extends ProcessObject { + + @Indexed + private String identifier; + private Version version; + private List<PetriNetIdentifier> parentIdentifiers; + private I18nString title; + private String icon; + private I18nExpression defaultCaseName; + private AccessPermissions<CasePermission> processRolePermissions; + private AccessPermissions<CasePermission> caseRolePermissions; + private Map<ProcessEventType, ProcessEvent> processEvents; + private Map<CaseEventType, CaseEvent> caseEvents; + private List<Function> functions; + private UniqueKeyMapWrapper<Field<?>> dataSet; + private UniqueKeyMapWrapper<Transition> transitions; + private UniqueKeyMapWrapper<Place> places; + private UniqueKeyMapWrapper<ArcCollection> arcs;//todo: import id + private UniqueKeyMapWrapper<String> properties; + + // TODO: 18. 3. 2017 replace with Spring auditing + private LocalDateTime creationDate; + private String authorId; + private String importXmlPath; + private String uriNodeId; + + public Process() { + this.id = new ObjectId(); + this.identifier = "Default"; + this.title = new I18nString(""); + this.importId = ""; + this.version = new Version(); + defaultCaseName = new I18nExpression(""); + parentIdentifiers = new ArrayList<>(); + creationDate = LocalDateTime.now(); + places = new UniqueKeyMapWrapper<>(); + transitions = new UniqueKeyMapWrapper<>(); + arcs = new UniqueKeyMapWrapper<>(); + dataSet = new UniqueKeyMapWrapper<>(); + processEvents = new HashMap<>(); + caseEvents = new HashMap<>(); + processRolePermissions = new AccessPermissions<>(); + caseRolePermissions = new AccessPermissions<>(); + functions = new LinkedList<>(); + properties = new UniqueKeyMapWrapper<>(); + } + + public void addParentIdentifier(PetriNetIdentifier identifier) { + parentIdentifiers.add(identifier); + } + + public void addPlace(Place place) { + this.places.put(place.getStringId(), place); + } + + public void addTransition(Transition transition) { + this.transitions.put(transition.getStringId(), transition); + } + + public void addProcessRolePermission(String actorId, Map<CasePermission, Boolean> permissions) { + this.processRolePermissions.addPermissions(actorId, permissions); + } + + public void addCaseRolePermission(String userListId, Map<CasePermission, Boolean> permissions) { + this.caseRolePermissions.addPermissions(userListId, permissions); + } + + public void addFunction(Function function) { + functions.add(function); + } + + public void addProcessEvent(ProcessEvent processEvent) { + processEvents.put(processEvent.getType(), processEvent); + } + + public void addCaseEvent(CaseEvent caseEvent) { + caseEvents.put(caseEvent.getType(), caseEvent); + } + + public List<PTArc> getInputArcsOf(String transitionId) { + if (arcs.containsKey(transitionId)) { + return arcs.get(transitionId).getInput(); + } + return new LinkedList<>(); + } + + public List<TPArc> getOutputArcsOf(String transitionId) { + if (arcs.containsKey(transitionId)) { + return arcs.get(transitionId).getOutput(); + } + return new LinkedList<>(); + } + + + public void addDataSetField(Field<?> field) { + this.dataSet.put(field.getStringId(), field); + } + + public void addArc(Arc<?, ?> arc) { + String transitionId = arc.getTransition().getStringId(); + ArcCollection arcCollection = arcs.get(transitionId); + if (arcCollection == null) { + arcCollection = new ArcCollection(); + arcs.put(transitionId, arcCollection); + } + if (arc instanceof PTArc) { + arcCollection.addInput((PTArc) arc); + } else { + arcCollection.addOutput((TPArc) arc); + } + } + + public Node getNode(String importId) { + if (places.containsKey(importId)) { + return getPlace(importId); + } + if (transitions.containsKey(importId)) { + return getTransition(importId); + } + return null; + } + + public Optional<Field<?>> getField(String id) { + return Optional.ofNullable(dataSet.get(id)); + } + + public Place getPlace(String id) { + return places.get(id); + } + + public Transition getTransition(String id) { + // TODO: release/8.0.0 change + if ("fake".equals(id)) { + return new Transition(); + } + return transitions.get(id); + } + + public void initializeArcs() { + arcs.values().forEach(list -> { + list.getOutput().forEach(arc -> { + arc.setSource(getTransition(arc.getSourceId())); + arc.setDestination(getPlace(arc.getDestinationId())); + }); + list.getInput().forEach(arc -> { + arc.setSource(getPlace(arc.getSourceId())); + arc.setDestination(getTransition(arc.getDestinationId())); + }); + }); + } + + public void initializeTokens(Map<String, Integer> activePlaces) { + places.values().forEach(place -> place.setTokens(activePlaces.getOrDefault(place.getStringId(), 0))); + } + + public Map<String, Integer> getActivePlaces() { + return places.values().stream() + .filter(Place::hasAnyTokens) + .collect(Collectors.toMap(ProcessObject::getStringId, Place::getTokens)); + } + + public void setActivePlaces(Map<String, Integer> activePlaces) { + places.forEach((id, place) -> { + Integer marking = activePlaces.getOrDefault(id, 0); + place.setTokens(marking); + }); + } + + public List<Field<?>> getImmediateFields() { + return this.dataSet.values().stream() + .filter((field) -> field.getImmediate() != null && field.getImmediate()) + .collect(Collectors.toList()); + } + + public void incrementVersion(VersionType type) { + this.version.increment(type); + } + + @Override + public String toString() { + return title.toString(); + } + + public String getTranslatedDefaultCaseName(Locale locale) { + if (defaultCaseName == null) { + return ""; + } + return defaultCaseName.getTranslation(locale); + } + + public List<Function> getFunctions(FunctionScope scope) { + return functions.stream().filter(function -> function.getScope().equals(scope)).collect(Collectors.toList()); + } + + public List<Action> getPreCreateActions() { + return getPreCaseActions(CaseEventType.CREATE); + } + + public List<Action> getPostCreateActions() { + return getPostCaseActions(CaseEventType.CREATE); + } + + public List<Action> getPreDeleteActions() { + return getPreCaseActions(CaseEventType.DELETE); + } + + public List<Action> getPostDeleteActions() { + return getPostCaseActions(CaseEventType.DELETE); + } + + public List<Action> getPreUploadActions() { + return getPreProcessActions(ProcessEventType.UPLOAD); + } + + public List<Action> getPostUploadActions() { + return getPostProcessActions(ProcessEventType.UPLOAD); + } + + private List<Action> getPreCaseActions(CaseEventType type) { + if (caseEvents.containsKey(type)) { + return caseEvents.get(type).getPreActions(); + } + return new LinkedList<>(); + } + + private List<Action> getPostCaseActions(CaseEventType type) { + if (caseEvents.containsKey(type)) { + return caseEvents.get(type).getPostActions(); + } + return new LinkedList<>(); + } + + private List<Action> getPreProcessActions(ProcessEventType type) { + if (processEvents.containsKey(type)) { + return processEvents.get(type).getPreActions(); + } + return new LinkedList<>(); + } + + private List<Action> getPostProcessActions(ProcessEventType type) { + if (processEvents.containsKey(type)) { + return processEvents.get(type).getPostActions(); + } + return new LinkedList<>(); + } + + public boolean hasDefaultCaseName() { + return defaultCaseName != null; + } + + @Override + public String getStringId() { + return id.toString(); + } + + public Process clone() { + Process clone = new Process(); + clone.setId(this.id); + clone.setIdentifier(this.identifier); + clone.setParentIdentifiers(this.parentIdentifiers.stream().map(PetriNetIdentifier::clone).collect(Collectors.toList())); + clone.setUriNodeId(this.uriNodeId); + clone.setTitle(this.title.clone()); + clone.setDefaultCaseName(this.defaultCaseName == null ? null : this.defaultCaseName.clone()); + clone.setIcon(this.icon); + clone.setCreationDate(this.creationDate); + clone.setVersion(this.version == null ? null : this.version.clone()); + clone.setTransitions(this.transitions == null ? null : new UniqueKeyMapWrapper<>(this.transitions)); + clone.setImportXmlPath(this.importXmlPath); + clone.setImportId(this.importId); + clone.setDataSet(new UniqueKeyMapWrapper<>(this.dataSet)); + clone.setPlaces(new UniqueKeyMapWrapper<>(this.places)); + clone.setArcs(new UniqueKeyMapWrapper<>(this.arcs)); + clone.initializeArcs(); + clone.setCaseEvents(this.caseEvents == null ? null : this.caseEvents.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone()))); + clone.setProcessEvents(this.processEvents == null ? null : this.processEvents.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone()))); + clone.setProcessRolePermissions(new AccessPermissions<>(this.processRolePermissions)); + clone.setCaseRolePermissions(new AccessPermissions<>(this.caseRolePermissions)); + this.getFunctions().forEach(clone::addFunction); + clone.setProperties(new UniqueKeyMapWrapper<>(this.properties)); + return clone; + } +} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNetObject.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/ProcessObject.java similarity index 70% rename from src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNetObject.java rename to src/main/java/com/netgrif/application/engine/petrinet/domain/ProcessObject.java index 951d5f565b9..5a27f452c5e 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/PetriNetObject.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/ProcessObject.java @@ -1,17 +1,25 @@ package com.netgrif.application.engine.petrinet.domain; import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import lombok.EqualsAndHashCode; import org.bson.types.ObjectId; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; +@EqualsAndHashCode(callSuper = true) +@Data @Document -public abstract class PetriNetObject extends Imported { +public abstract class ProcessObject extends Imported { @Id @JsonIgnore protected ObjectId id; + public ProcessObject() { + this.id = new ObjectId(); + } + public String getStringId() { return importId; } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/Transaction.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/Transaction.java index 5d039caed10..9eedd1a82db 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/Transaction.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/Transaction.java @@ -14,7 +14,7 @@ * transitions' ObjectId. */ @Document -public class Transaction extends PetriNetObject { +public class Transaction extends ProcessObject { @Getter @Setter diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/Transition.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/Transition.java index 425333d59b0..171b84584f7 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/Transition.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/Transition.java @@ -1,32 +1,26 @@ package com.netgrif.application.engine.petrinet.domain; +import com.netgrif.application.engine.authorization.domain.permissions.AccessPermissions; import com.netgrif.application.engine.importer.model.DataEventType; import com.netgrif.application.engine.importer.model.EventType; import com.netgrif.application.engine.petrinet.domain.dataset.Field; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.FieldBehavior; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.FieldLayout; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; import com.netgrif.application.engine.petrinet.domain.events.DataEvent; import com.netgrif.application.engine.petrinet.domain.events.Event; -import com.netgrif.application.engine.petrinet.domain.layout.TaskLayout; +import com.netgrif.application.engine.petrinet.domain.layout.LayoutContainer; import com.netgrif.application.engine.petrinet.domain.policies.AssignPolicy; -import com.netgrif.application.engine.petrinet.domain.policies.DataFocusPolicy; import com.netgrif.application.engine.petrinet.domain.policies.FinishPolicy; -import com.netgrif.application.engine.petrinet.domain.roles.AssignedUserPermission; -import com.netgrif.application.engine.petrinet.domain.roles.RolePermission; +import com.netgrif.application.engine.authorization.domain.permissions.TaskPermission; +import com.netgrif.application.engine.utils.UniqueKeyMapWrapper; import com.netgrif.application.engine.workflow.domain.DataFieldBehavior; import com.netgrif.application.engine.workflow.domain.triggers.AutoTrigger; import com.netgrif.application.engine.workflow.domain.triggers.Trigger; -import com.querydsl.core.annotations.PropertyType; -import com.querydsl.core.annotations.QueryType; import lombok.Getter; import lombok.Setter; import org.springframework.data.annotation.Transient; -import org.apache.lucene.analysis.CharArrayMap; import org.springframework.data.mongodb.core.mapping.Document; import java.util.*; -import java.util.function.Consumer; import java.util.stream.Collectors; @Document @@ -34,70 +28,40 @@ @Setter public class Transition extends Node { - @org.springframework.data.mongodb.core.mapping.Field("dataGroups") - private Map<String, DataGroup> dataGroups; - @org.springframework.data.mongodb.core.mapping.Field("dataSet") + private String icon; private LinkedHashMap<String, DataRef> dataSet; - @org.springframework.data.mongodb.core.mapping.Field("roles") - private Map<String, Map<RolePermission, Boolean>> roles; - private List<String> negativeViewRoles; - @org.springframework.data.mongodb.core.mapping.Field("users") - private Map<String, Map<RolePermission, Boolean>> userRefs; - @org.springframework.data.mongodb.core.mapping.Field("triggers") + private AccessPermissions<TaskPermission> processRolePermissions; + private AccessPermissions<TaskPermission> caseRolePermissions; private List<Trigger> triggers; - @QueryType(PropertyType.NONE) - private TaskLayout layout; - private Integer priority; + private LayoutContainer layoutContainer; private AssignPolicy assignPolicy; - private String icon; - private DataFocusPolicy dataFocusPolicy; private FinishPolicy finishPolicy; private Map<EventType, Event> events; - private Map<AssignedUserPermission, Boolean> assignedUserPolicy; - private String defaultRoleId; @Transient private Boolean hasAutoTrigger; - private Map<String, String> tags; public Transition() { super(); dataSet = new LinkedHashMap<>(); - roles = new HashMap<>(); - userRefs = new HashMap<>(); triggers = new LinkedList<>(); - negativeViewRoles = new LinkedList<>(); - dataGroups = new LinkedHashMap<>(); assignPolicy = AssignPolicy.MANUAL; - dataFocusPolicy = DataFocusPolicy.MANUAL; finishPolicy = FinishPolicy.MANUAL; events = new HashMap<>(); - assignedUserPolicy = new HashMap<>(); - tags = new HashMap<>(); + processRolePermissions = new AccessPermissions<>(); + caseRolePermissions = new AccessPermissions<>(); } public void setDataRefBehavior(Field<?> field, DataFieldBehavior behavior) { // TODO: release/8.0.0 - setDataRefAttribute(field, dataRef -> { - field.setBehavior(this.importId, behavior); - dataRef.setBehavior(behavior); - }); +// setDataRefAttribute(field, dataRef -> { +// field.setBehavior(this.importId, behavior); +// dataRef.setBehavior(behavior); +// }); } public void setDataRefComponent(Field<?> field, Component component) { - setDataRefAttribute(field, dataRef -> dataRef.setComponent(component)); - } - - public void setDataRefLayout(Field<?> field, FieldLayout fieldLayout) { - setDataRefAttribute(field, dataRef -> dataRef.setLayout(fieldLayout)); - } - - private void setDataRefAttribute(Field<?> field, Consumer<DataRef> attributeChange) { - String fieldId = field.getStringId(); - if (!dataSet.containsKey(fieldId)) { - dataSet.put(fieldId, new DataRef(field)); - } - DataRef dataRef = dataSet.get(fieldId); - attributeChange.accept(dataRef); + // TODO: release/8.0.0 +// setDataRefAttribute(field, dataRef -> dataRef.setComponent(component)); } public void setDataEvents(String field, Map<DataEventType, DataEvent> events) { @@ -106,28 +70,12 @@ public void setDataEvents(String field, Map<DataEventType, DataEvent> events) { } } - public void addRole(String roleId, Map<RolePermission, Boolean> permissions) { - if (roles.containsKey(roleId) && roles.get(roleId) != null) { - roles.get(roleId).putAll(permissions); - } else { - roles.put(roleId, permissions); - } - } - - public void addNegativeViewRole(String roleId) { - negativeViewRoles.add(roleId); - } - - public void addUserRef(String userRefId, Map<RolePermission, Boolean> permissions) { - if (userRefs.containsKey(userRefId) && userRefs.get(userRefId) != null) { - userRefs.get(userRefId).putAll(permissions); - } else { - userRefs.put(userRefId, permissions); - } + public void addProcessRolePermission(String roleId, Map<TaskPermission, Boolean> permissions) { + this.processRolePermissions.addPermissions(roleId, permissions); } - public void addDataGroup(DataGroup dataGroup) { - dataGroups.put(dataGroup.getStringId(), dataGroup); + public void addCaseRolePermission(String userRefId, Map<TaskPermission, Boolean> permissions) { + this.caseRolePermissions.addPermissions(userRefId, permissions); } public void addTrigger(Trigger trigger) { @@ -158,23 +106,17 @@ public List<Action> getPostCancelActions() { return getPostActions(EventType.CANCEL); } - public List<Action> getPreDelegateActions() { - return getPreActions(EventType.DELEGATE); - } - - public List<Action> getPostDelegateActions() { - return getPostActions(EventType.DELEGATE); - } - private List<Action> getPreActions(EventType type) { - if (events.containsKey(type)) + if (events.containsKey(type)) { return events.get(type).getPreActions(); + } return new LinkedList<>(); } private List<Action> getPostActions(EventType type) { - if (events.containsKey(type)) + if (events.containsKey(type)) { return events.get(type).getPostActions(); + } return new LinkedList<>(); } @@ -190,13 +132,10 @@ public I18nString getCancelMessage() { return getMessage(EventType.CANCEL); } - public I18nString getDelegateMessage() { - return getMessage(EventType.DELEGATE); - } - private I18nString getMessage(EventType type) { - if (events.containsKey(type)) + if (events.containsKey(type)) { return events.get(type).getMessage(); + } return null; } @@ -238,26 +177,20 @@ public LinkedHashSet<String> getImmediateData() { @Override public Transition clone() { + // TODO: release/8.0.0 Transition clone = new Transition(); clone.setTitle(this.getTitle() == null ? null : this.getTitle().clone()); - clone.setPosition(this.getPosition().getX(), this.getPosition().getY()); clone.setImportId(this.importId); - clone.setDataGroups(this.dataGroups == null ? null : dataGroups.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x, y) -> y.clone(), LinkedHashMap::new))); clone.setDataSet(this.dataSet == null ? null : dataSet.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x, y) -> y.clone(), LinkedHashMap::new))); - clone.setRoles(this.roles == null ? null : roles.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new HashMap<>(e.getValue())))); - clone.setNegativeViewRoles(new ArrayList<>(negativeViewRoles)); - clone.setUserRefs(this.userRefs == null ? null : userRefs.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new HashMap<>(e.getValue())))); clone.setTriggers(this.triggers == null ? null : triggers.stream().map(Trigger::clone).collect(Collectors.toList())); - clone.setLayout(this.layout == null ? null : layout.clone()); - clone.setPriority(priority); clone.setAssignPolicy(assignPolicy); clone.setIcon(icon); - clone.setDataFocusPolicy(dataFocusPolicy); clone.setFinishPolicy(finishPolicy); clone.setEvents(this.events == null ? null : events.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone()))); - clone.setAssignedUserPolicy(new HashMap<>(assignedUserPolicy)); - clone.setTags(new HashMap<>(this.tags)); - clone.setDefaultRoleId(defaultRoleId); + clone.setProperties(new UniqueKeyMapWrapper<>(this.getProperties())); + clone.setLayoutContainer(this.layoutContainer == null ? null : this.layoutContainer.clone()); + clone.setProcessRolePermissions(new AccessPermissions<>(this.processRolePermissions)); + clone.setCaseRolePermissions(new AccessPermissions<>(this.caseRolePermissions)); return clone; } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/Arc.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/Arc.java index 7f3a462aae8..fe596e31de9 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/Arc.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/Arc.java @@ -1,55 +1,49 @@ package com.netgrif.application.engine.petrinet.domain.arcs; import com.netgrif.application.engine.petrinet.domain.*; -import com.netgrif.application.engine.petrinet.domain.arcs.reference.Reference; -import lombok.Getter; -import lombok.Setter; +import com.netgrif.application.engine.utils.UniqueKeyMapWrapper; +import lombok.Data; import org.bson.types.ObjectId; import org.springframework.data.annotation.Transient; import java.util.ArrayList; import java.util.List; -public class Arc extends PetriNetObject { +@Data +public abstract class Arc<S extends Node, D extends Node> extends ProcessObject { @Transient - protected Node source; - - @Getter - @Setter + protected S source; protected String sourceId; - @Transient - protected Node destination; - - @Getter - @Setter + protected D destination; protected String destinationId; - - @Getter - @Setter - protected Integer multiplicity; - - @Getter - @Setter - protected Reference reference; - - @Getter - @Setter + protected Multiplicity multiplicityExpression; protected List<Position> breakpoints; + protected UniqueKeyMapWrapper<String> properties; public Arc() { this.setObjectId(new ObjectId()); this.breakpoints = new ArrayList<>(); + this.properties = new UniqueKeyMapWrapper<>(); } - public Arc(Node source, Node destination, int multiplicity) { + public Arc(S source, D destination, int multiplicity) { this(); this.setSource(source); this.setDestination(destination); - this.multiplicity = multiplicity; + this.multiplicityExpression = new Multiplicity(multiplicity); } + public Arc(S source, D destination, String multiplicity) { + this(); + this.setSource(source); + this.setDestination(destination); + this.multiplicityExpression = new Multiplicity(multiplicity); + } + + public abstract void execute(); + public Place getPlace() { return (source instanceof Place) ? ((Place) source) : ((Place) destination); } @@ -58,69 +52,26 @@ public Transition getTransition() { return (source instanceof Transition) ? ((Transition) source) : ((Transition) destination); } - public Node getSource() { - return source; - } - - public void setSource(Node source) { + public void setSource(S source) { this.source = source; this.sourceId = source.getImportId(); } - public Node getDestination() { - return destination; - } - - public void setDestination(Node destination) { + public void setDestination(D destination) { this.destination = destination; this.destinationId = destination.getImportId(); } - @Override - public String toString() { - return source.getTitle() + " -(" + multiplicity + ")> " + destination.getTitle(); - } - - public boolean isExecutable() { - if (source instanceof Transition) - return true; - if (this.reference != null) { - this.multiplicity = this.reference.getMultiplicity(); - } - return ((Place) source).getTokens() >= multiplicity; - } - - public void execute() { - if (reference != null) { - multiplicity = reference.getMultiplicity(); - } - if (source instanceof Transition) { - ((Place) destination).addTokens(multiplicity); - } else { - ((Place) source).removeTokens(multiplicity); - } + public int getMultiplicity() { + return this.multiplicityExpression.getMultiplicity(); } - public void rollbackExecution(Integer tokensConsumed) { - if (tokensConsumed == null && this.reference != null) { - throw new IllegalArgumentException("Cannot rollback variable arc, because it was never executed"); - } - if (this.reference == null) { - tokensConsumed = multiplicity; - } - ((Place) source).addTokens(tokensConsumed); + public void setMultiplicity(int weight) { + this.multiplicityExpression.setMultiplicity(weight); } - @SuppressWarnings("Duplicates") - public Arc clone() { - Arc clone = new Arc(); - clone.setSourceId(this.sourceId); - clone.setDestinationId(this.destinationId); - clone.setMultiplicity(this.multiplicity); - clone.setBreakpoints(this.breakpoints); - clone.setObjectId(this.getObjectId()); - clone.setImportId(this.importId); - clone.setReference(this.reference == null ? null : this.reference.clone()); - return clone; + @Override + public String toString() { + return source.getTitle() + " -(" + multiplicityExpression + ")> " + destination.getTitle(); } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ArcCollection.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ArcCollection.java new file mode 100644 index 00000000000..b2e66e747ed --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ArcCollection.java @@ -0,0 +1,40 @@ +package com.netgrif.application.engine.petrinet.domain.arcs; + +import com.netgrif.application.engine.petrinet.domain.Node; +import lombok.Data; +import org.apache.commons.collections.ListUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class ArcCollection { + // TODO: release/8.0.0 save sorted by execution priority + private List<PTArc> input; + private List<TPArc> output; + + public ArcCollection() { + input = new ArrayList<>(); + output = new ArrayList<>(); + } + + public void addInput(PTArc arc) { + this.input.add(arc); + } + + public void addOutput(TPArc arc) { + this.output.add(arc); + } + + public int size() { + return input.size() + output.size(); + } + + public ArcCollection clone() { + ArcCollection cloned = new ArcCollection(); + cloned.input = this.input.stream().map(PTArc::clone).collect(Collectors.toList()); + cloned.output = this.output.stream().map(TPArc::clone).collect(Collectors.toList()); + return cloned; + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ArcOrderComparator.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ArcOrderComparator.java index d37c01d9588..2d75f412d84 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ArcOrderComparator.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ArcOrderComparator.java @@ -2,7 +2,7 @@ public class ArcOrderComparator { - private static ArcOrderComparator ourInstance = new ArcOrderComparator(); + private static final ArcOrderComparator ourInstance = new ArcOrderComparator(); private ArcOrderComparator() { } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/InhibitorArc.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/InhibitorArc.java index 3b1a5263fff..8dc2dfdef40 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/InhibitorArc.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/InhibitorArc.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.petrinet.domain.arcs; -import com.netgrif.application.engine.petrinet.domain.Place; +import com.netgrif.application.engine.petrinet.domain.throwable.IllegalMarkingException; /** * If there is an arc <i>a</i> with a weight <i>w=W(p,t)</i> connecting a place <i>p</i> with a transition <i>t</i>, @@ -19,8 +19,7 @@ public class InhibitorArc extends PTArc { */ @Override public boolean isExecutable() { - if (this.reference != null) multiplicity = this.reference.getMultiplicity(); - return ((Place) source).getTokens() < multiplicity; + return source.getTokens() < this.getMultiplicity(); } /** @@ -28,6 +27,9 @@ public boolean isExecutable() { */ @Override public void execute() { + if (!this.isExecutable()) { + throw new IllegalMarkingException(this.source); + } } /** @@ -37,16 +39,14 @@ public void execute() { public void rollbackExecution(Integer tokensConsumed) { } - @SuppressWarnings("Duplicates") @Override public InhibitorArc clone() { InhibitorArc clone = new InhibitorArc(); clone.setSourceId(this.sourceId); clone.setDestinationId(this.destinationId); - clone.setMultiplicity(this.multiplicity); + clone.setMultiplicityExpression(this.multiplicityExpression.clone()); clone.setObjectId(this.getObjectId()); clone.setImportId(this.importId); - clone.setReference(this.reference == null ? null : this.reference.clone()); return clone; } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/Multiplicity.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/Multiplicity.java new file mode 100644 index 00000000000..1d5fd6561ae --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/Multiplicity.java @@ -0,0 +1,36 @@ +package com.netgrif.application.engine.petrinet.domain.arcs; + +import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class Multiplicity extends Expression<Integer> { + private Integer multiplicity; + private ReferenceType referenceType; + + public Multiplicity(int multiplicity) { + super(multiplicity, null); + this.multiplicity = multiplicity; + } + + public Multiplicity(String definition) { + super(null, definition); + } + + public Multiplicity(String referenceId, ReferenceType type) { + this(referenceId); + this.referenceType = type; + } + + public Multiplicity clone() { + if (this.getDefaultValue() != null) { + return new Multiplicity(this.multiplicity); + } + return new Multiplicity(this.getDefinition(), this.referenceType); + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/PTArc.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/PTArc.java index 3ed8203259f..f81685b1f41 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/PTArc.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/PTArc.java @@ -1,37 +1,16 @@ package com.netgrif.application.engine.petrinet.domain.arcs; -import com.netgrif.application.engine.petrinet.domain.Node; import com.netgrif.application.engine.petrinet.domain.Place; import com.netgrif.application.engine.petrinet.domain.Transition; /** - * Special arcs that can only lead from Place to Transition (thus PT). + * Arcs that can only lead from Place to Transition (thus PT). */ -public abstract class PTArc extends Arc { +public abstract class PTArc extends Arc<Place, Transition> { - /** - * Sets source of this arc. - * - * @param source Node object of class Place - * @throws IllegalArgumentException if <i>source</i> is of class Transition - */ - @Override - public void setSource(Node source) { - if (source instanceof Transition) - throw new IllegalArgumentException(this.getClass().getSimpleName() + " can not lead from a Transition"); - super.setSource(source); - } + public abstract boolean isExecutable(); - /** - * Sets destination of this arc. - * - * @param destination Node object of class Transition - * @throws IllegalArgumentException if <i>destination</i> is of class Place - */ - @Override - public void setDestination(Node destination) { - if (destination instanceof Place) - throw new IllegalArgumentException(this.getClass().getSimpleName() + " can not lead to a Place"); - super.setDestination(destination); - } + public abstract void rollbackExecution(Integer tokensConsumed); + + public abstract PTArc clone(); } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ReadArc.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ReadArc.java index 8e75255574e..86a9a17c9a0 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ReadArc.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ReadArc.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.petrinet.domain.arcs; -import com.netgrif.application.engine.petrinet.domain.Place; +import com.netgrif.application.engine.petrinet.domain.throwable.IllegalMarkingException; /** * If there is an arc <i>a</i> with a weight <i>w=W(p,t)</i> connecting a place <i>p</i> with a transition <i>t</i>, @@ -19,8 +19,7 @@ public class ReadArc extends PTArc { */ @Override public boolean isExecutable() { - if (this.reference != null) multiplicity = this.reference.getMultiplicity(); - return ((Place) source).getTokens() >= multiplicity; + return source.getTokens() >= this.getMultiplicity(); } /** @@ -28,6 +27,9 @@ public boolean isExecutable() { */ @Override public void execute() { + if (!this.isExecutable()) { + throw new IllegalMarkingException(this.source); + } } /** @@ -43,10 +45,9 @@ public ReadArc clone() { ReadArc clone = new ReadArc(); clone.setSourceId(this.sourceId); clone.setDestinationId(this.destinationId); - clone.setMultiplicity(this.multiplicity); + clone.setMultiplicityExpression(this.multiplicityExpression.clone()); clone.setObjectId(this.getObjectId()); clone.setImportId(this.importId); - clone.setReference(this.reference == null ? null : this.reference.clone()); return clone; } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ReferenceType.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ReferenceType.java new file mode 100644 index 00000000000..507f11a2f6d --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ReferenceType.java @@ -0,0 +1,6 @@ +package com.netgrif.application.engine.petrinet.domain.arcs; + +public enum ReferenceType { + PLACE, + DATA_VARIABLE +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/RegularPTArc.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/RegularPTArc.java new file mode 100644 index 00000000000..8a1c75cef35 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/RegularPTArc.java @@ -0,0 +1,30 @@ +package com.netgrif.application.engine.petrinet.domain.arcs; + +public class RegularPTArc extends PTArc { + + @Override + public boolean isExecutable() { + return source.getTokens() >= this.getMultiplicity(); + } + + @Override + public void execute() { + source.removeTokens(this.getMultiplicity()); + } + + @Override + public void rollbackExecution(Integer tokensConsumed) { + source.addTokens(tokensConsumed); + } + + @Override + public RegularPTArc clone() { + RegularPTArc clone = new RegularPTArc(); + clone.setSourceId(this.sourceId); + clone.setDestinationId(this.destinationId); + clone.setMultiplicityExpression(this.multiplicityExpression.clone()); + clone.setObjectId(this.getObjectId()); + clone.setImportId(this.importId); + return clone; + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/RegularTPArc.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/RegularTPArc.java new file mode 100644 index 00000000000..1e7eefc80ee --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/RegularTPArc.java @@ -0,0 +1,20 @@ +package com.netgrif.application.engine.petrinet.domain.arcs; + +public class RegularTPArc extends TPArc { + + @Override + public void execute() { + this.destination.addTokens(this.getMultiplicity()); + } + + @Override + public RegularTPArc clone() { + RegularTPArc clone = new RegularTPArc(); + clone.setSourceId(this.sourceId); + clone.setDestinationId(this.destinationId); + clone.setMultiplicityExpression(this.multiplicityExpression.clone()); + clone.setObjectId(this.getObjectId()); + clone.setImportId(this.importId); + return clone; + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ResetArc.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ResetArc.java index 1e6b3924467..6213fad5be8 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ResetArc.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/ResetArc.java @@ -1,7 +1,5 @@ package com.netgrif.application.engine.petrinet.domain.arcs; -import com.netgrif.application.engine.petrinet.domain.Place; - /** * Reset arc does not alter the enabling condition, but involve a change of the marking on <i>p</i> by firing of <i>t</i>: * <ul> @@ -31,22 +29,20 @@ public boolean isExecutable() { */ @Override public void execute() { - Place place = ((Place) source); - place.removeAllTokens(); + source.removeAllTokens(); } @Override public void rollbackExecution(Integer tokensConsumed) { - ((Place) source).addTokens(tokensConsumed); + source.addTokens(tokensConsumed); } - @SuppressWarnings("Duplicates") @Override public ResetArc clone() { ResetArc clone = new ResetArc(); clone.setSourceId(this.sourceId); clone.setDestinationId(this.destinationId); - clone.setMultiplicity(this.multiplicity); + clone.setMultiplicityExpression(this.multiplicityExpression.clone()); clone.setObjectId(this.getObjectId()); clone.setImportId(this.importId); return clone; diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/TPArc.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/TPArc.java new file mode 100644 index 00000000000..6e698fac05b --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/TPArc.java @@ -0,0 +1,12 @@ +package com.netgrif.application.engine.petrinet.domain.arcs; + +import com.netgrif.application.engine.petrinet.domain.Place; +import com.netgrif.application.engine.petrinet.domain.Transition; + +/** + * Arcs that can only lead from Transition to Place (thus TP). + */ +public abstract class TPArc extends Arc<Transition, Place> { + + public abstract TPArc clone(); +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/VariableArc.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/VariableArc.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/reference/Referencable.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/reference/Referencable.java deleted file mode 100644 index 22ab1286774..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/reference/Referencable.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.arcs.reference; - -public interface Referencable { - - int getMultiplicity(); - -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/reference/Reference.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/reference/Reference.java deleted file mode 100644 index 57758de938e..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/reference/Reference.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.arcs.reference; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.springframework.data.annotation.Transient; - -import java.io.Serializable; - - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class Reference implements Serializable { - - private static final long serialVersionUID = 7082645066561158952L; - - private String reference; - - private Type type; - - @Transient - private Referencable referencable; - - public Reference(String reference, Type type) { - this.reference = reference; - this.type = type; - } - - public int getMultiplicity() { - int multiplicity = this.referencable.getMultiplicity(); - if (multiplicity < 0) { - throw new IllegalStateException("Referenced object " + reference + " has invalid multiplicity: " + multiplicity); - } - return multiplicity; - } - - public Reference clone() { - return new Reference(this.reference, this.type); - } - -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/reference/Type.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/reference/Type.java deleted file mode 100644 index be2e37eb5dc..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/arcs/reference/Type.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.arcs.reference; - -public enum Type { - - PLACE, - DATA -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/Arguments.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/Arguments.java new file mode 100644 index 00000000000..e9aab419667 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/Arguments.java @@ -0,0 +1,38 @@ +package com.netgrif.application.engine.petrinet.domain.dataset; + +import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@Data +@AllArgsConstructor +public class Arguments implements Serializable { + + private static final long serialVersionUID = -2385696520525471923L; + + private ArrayList<Expression<String>> argument; + + public Arguments() { + this.argument = new ArrayList<>(); + } + + public void addArgument(Expression<String> argument) { + this.argument.add(argument); + } + + @Override + public Arguments clone() { + Arguments cloned = new Arguments(); + if (argument != null) { + ArrayList<Expression<String>> clonedArgument = new ArrayList<>(); + argument.forEach(a -> clonedArgument.add(a.clone())); + cloned.setArgument(clonedArgument); + } + return cloned; + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/BooleanField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/BooleanField.java index 6f7ee709a21..652f430b9a2 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/BooleanField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/BooleanField.java @@ -8,7 +8,6 @@ public class BooleanField extends Field<Boolean> { public BooleanField() { super(); - defaultValue = false; } @Override diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/CaseField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/CaseField.java index 4d118eed641..d3366364c67 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/CaseField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/CaseField.java @@ -5,7 +5,6 @@ import com.querydsl.core.annotations.QueryType; import lombok.NoArgsConstructor; -import java.util.ArrayList; import java.util.List; @NoArgsConstructor @@ -13,7 +12,15 @@ public class CaseField extends FieldWithAllowedNets<List<String>> { public CaseField(List<String> allowedNets) { super(allowedNets); - super.defaultValue = new ArrayList<>(); + } + + /** + * todo javadoc + * */ + public static CaseField withValue(List<String> value) { + CaseField field = new CaseField(); + field.setRawValue(value); + return field; } @Override diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/ChoiceField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/ChoiceField.java index 58bea2b823e..6b09c210e97 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/ChoiceField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/ChoiceField.java @@ -4,16 +4,14 @@ import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; import lombok.Data; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; +import java.util.*; @Data +// TODO: release/8.0.0 rename public abstract class ChoiceField<T> extends Field<T> { - protected Set<I18nString> choices; - protected Expression choicesExpression; + protected LinkedHashSet<I18nString> choices; + protected Expression<LinkedHashSet<I18nString>> choicesExpression; public ChoiceField() { super(); @@ -23,20 +21,23 @@ public ChoiceField() { public ChoiceField(List<I18nString> choices) { this(); if (choices != null) { + if (this.choices == null) { + this.choices = new LinkedHashSet<>(); + } this.choices.addAll(choices); } } - public ChoiceField(Expression expression) { + public ChoiceField(Expression<LinkedHashSet<I18nString>> expression) { this(); this.choicesExpression = expression; } - public Expression getExpression() { + public Expression<LinkedHashSet<I18nString>> getExpression() { return choicesExpression; } - public void setExpression(Expression choicesExpression) { + public void setExpression(Expression<LinkedHashSet<I18nString>> choicesExpression) { this.choicesExpression = choicesExpression; } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/DateTimeField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/DateTimeField.java index 4940abaffb5..eef7da0b093 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/DateTimeField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/DateTimeField.java @@ -12,6 +12,11 @@ public DateTimeField() { super(); } + public DateTimeField(LocalDateTime dateTime) { + this(); + setRawValue(dateTime); + } + @Override @QueryType(PropertyType.NONE) public DataType getType() { diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/EnumerationMapField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/EnumerationMapField.java index 62a63604bea..40ce6ffa2de 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/EnumerationMapField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/EnumerationMapField.java @@ -18,6 +18,11 @@ public EnumerationMapField() { super(); } + public EnumerationMapField(String value) { + this(); + setRawValue(value); + } + @Override @QueryType(PropertyType.NONE) public DataType getType() { diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/Field.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/Field.java index fe24621f141..789d2b1bd49 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/Field.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/Field.java @@ -12,13 +12,14 @@ import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; import com.netgrif.application.engine.petrinet.domain.events.DataEvent; import com.netgrif.application.engine.utils.FieldUtils; +import com.netgrif.application.engine.utils.UniqueKeyMapWrapper; import com.netgrif.application.engine.workflow.domain.DataFieldBehavior; import com.netgrif.application.engine.workflow.domain.DataFieldBehaviors; import com.netgrif.application.engine.workflow.domain.DataFieldValue; import com.querydsl.core.annotations.PropertyType; import com.querydsl.core.annotations.QueryType; import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; import net.minidev.json.annotate.JsonIgnore; import org.bson.types.ObjectId; @@ -30,11 +31,12 @@ import static com.netgrif.application.engine.petrinet.domain.dataset.logic.FieldBehavior.*; + @Slf4j @Document @Data -@NoArgsConstructor @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type") +// TODO: release/8.0.0 check with new schema @JsonSubTypes({ @JsonSubTypes.Type(value = BooleanField.class, name = "BOOLEAN"), @JsonSubTypes.Type(value = ButtonField.class, name = "BUTTON"), @@ -42,7 +44,7 @@ @JsonSubTypes.Type(value = DateField.class, name = "DATE"), @JsonSubTypes.Type(value = DateTimeField.class, name = "DATE_TIME"), @JsonSubTypes.Type(value = EnumerationField.class, name = "ENUMERATION"), - @JsonSubTypes.Type(value = EnumerationMapField.class, name = "ENUMERATION_MAP_FIELD"), + @JsonSubTypes.Type(value = EnumerationMapField.class, name = "ENUMERATION_MAP"), @JsonSubTypes.Type(value = FileField.class, name = "FILE"), @JsonSubTypes.Type(value = FileListField.class, name = "FILE_LIST"), @JsonSubTypes.Type(value = FilterField.class, name = "FILTER"), @@ -50,36 +52,43 @@ @JsonSubTypes.Type(value = MultichoiceField.class, name = "MULTICHOICE"), @JsonSubTypes.Type(value = MultichoiceMapField.class, name = "MULTICHOICE_MAP"), @JsonSubTypes.Type(value = NumberField.class, name = "NUMBER"), + // TODO: release/8.0.0 check name value + @JsonSubTypes.Type(value = StringCollectionField.class, name = "STRINGCOLLECTION"), @JsonSubTypes.Type(value = TaskField.class, name = "TASK_REF"), @JsonSubTypes.Type(value = TextField.class, name = "TEXT"), @JsonSubTypes.Type(value = UserField.class, name = "USER"), @JsonSubTypes.Type(value = UserListField.class, name = "USER_LIST"), }) +@EqualsAndHashCode(callSuper = true) public abstract class Field<T> extends Imported { @Id protected ObjectId id; - @JsonIgnore - protected T defaultValue; - @JsonIgnore - protected Expression initExpression; - protected List<Validation> validations; - private I18nString name; //title + private I18nString title; private I18nString description; private I18nString placeholder; + // TODO: release/8.0.0 dataset or task? private DataFieldBehaviors behaviors; private DataFieldValue<T> value; @JsonIgnore - private Boolean immediate; + protected Expression<T> defaultValue; + protected List<Validation> validations; @JsonIgnore - private Map<DataEventType, DataEvent> events; + private Boolean immediate; @JsonIgnore private String encryption; - private Integer length; private Component component; @JsonIgnore + private Map<DataEventType, DataEvent> events; + // TODO: release/8.0.0 remove? + @JsonIgnore private Long version = 0L; // TODO: release/8.0.0 6.2.5: parentTaskId, parentCaseId + private UniqueKeyMapWrapper<String> properties; + + public Field() { + // TODO: release/8.0.0 no collection can be initialised + } public String getStringId() { return importId; @@ -102,8 +111,8 @@ public T getRawValue() { return this.value.getValue(); } - public boolean isImmediate() { - return this.immediate != null && this.immediate; + public void applyDefaultValue() { + this.setRawValue(this.getDefaultValue().getDefaultValue()); } public void addActions(Collection<Action> dataEvents, DataEventType type) { @@ -128,8 +137,8 @@ public void addAction(Action action, DataEventType type) { } } - public boolean isDynamicDefaultValue() { - return initExpression != null; + public void addEvent(DataEvent event) { + events.put(event.getType(), event); } public void addValidation(Validation validation) { @@ -143,8 +152,11 @@ public void clearValue() { this.value = null; } - public boolean hasDefault() { - return defaultValue != null || initExpression != null; + public boolean isImmediate() { + if (immediate == null) { + return false; + } + return immediate; } public boolean isNewerThen(Field<?> field) { @@ -153,29 +165,31 @@ public boolean isNewerThen(Field<?> field) { @Override public String toString() { - return name.getDefaultValue(); + return title.getDefaultValue(); } public void clone(Field<T> clone) { clone.importId = this.importId; clone.id = this.id; - clone.defaultValue = this.defaultValue; - if (this.initExpression != null) { - clone.initExpression = this.initExpression.clone(); +// TODO: release/8.0.0 clone value? events + if (this.defaultValue != null) { + clone.defaultValue = this.defaultValue.clone(); } if (this.validations != null) { clone.validations = this.validations.stream().map(Validation::clone).collect(Collectors.toList()); } - clone.name = this.name; - clone.description = this.description; - clone.placeholder = this.placeholder; + if (this.title != null) { + clone.title = this.title.clone(); + } + if (this.description != null) { + clone.description = this.description.clone(); + } + if (this.placeholder != null) { + clone.placeholder = this.placeholder.clone(); + } if (this.behaviors != null) { clone.behaviors = this.behaviors.clone(); } -// TODO: release/8.0.0 clone value? events -// if (this.value != null) { -// clone.value = this.value.clone(); -// } clone.immediate = this.immediate; if (this.events != null) { clone.events = this.events.entrySet() @@ -183,8 +197,12 @@ public void clone(Field<T> clone) { .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone())); } clone.encryption = this.encryption; - clone.length = this.length; - clone.component = this.component; + if (this.component != null) { + clone.component = this.component.clone(); + } + if (this.properties != null) { + clone.properties = this.properties.clone(); + } } public abstract Field<T> clone(); @@ -218,11 +236,11 @@ private boolean isBehaviorSetOn(String transitionId, FieldBehavior behavior) { } @JsonIgnore - public String getTranslatedName(Locale locale) { - if (name == null) { + public String getTranslatedTitle(Locale locale) { + if (title == null) { return null; } - return name.getTranslation(locale); + return title.getTranslation(locale); } /** @@ -242,8 +260,4 @@ public void applyChanges(Field<?> changes) { } version++; } - - public void applyDefaultValue() { - this.setRawValue(this.getDefaultValue()); - } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/FieldWithAllowedRoles.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/FieldWithAllowedRoles.java new file mode 100644 index 00000000000..fc4ecef8c43 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/FieldWithAllowedRoles.java @@ -0,0 +1,33 @@ +package com.netgrif.application.engine.petrinet.domain.dataset; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.HashSet; +import java.util.Set; + +@Data +@EqualsAndHashCode(callSuper = true) +public abstract class FieldWithAllowedRoles<T> extends Field<T> { + + private Set<String> allowedRoleImportIds; + private Set<String> caseRoleIds; + + public FieldWithAllowedRoles() { + super(); + this.caseRoleIds = new HashSet<>(); + } + + public FieldWithAllowedRoles(Set<String> allowedRoleImportIds) { + this(); + this.setAllowedRoleImportIds(allowedRoleImportIds); + } + + public void clone(FieldWithAllowedRoles<T> clone) { + super.clone(clone); + if (allowedRoleImportIds != null) { + clone.allowedRoleImportIds = new HashSet<>(allowedRoleImportIds); + } + clone.setCaseRoleIds(new HashSet<>(caseRoleIds)); + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/FileField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/FileField.java index afb25c4d660..6713822cc18 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/FileField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/FileField.java @@ -10,8 +10,6 @@ @Data public class FileField extends Field<FileFieldValue> { - private Boolean remote; - public FileField() { super(); } @@ -26,10 +24,6 @@ public void setValue(String value) { this.setRawValue(FileFieldValue.fromString(value)); } - public void setDefaultValue(String defaultValue) { - this.setDefaultValue(FileFieldValue.fromString(defaultValue)); - } - /** * Get complete file path to the file * Path is generated as follow: @@ -41,7 +35,7 @@ public void setDefaultValue(String defaultValue) { * @return path to the saved file */ public String getFilePath(String caseId) { - if (this.remote) { + if (this.isRemote()) { return this.getValue().getValue().getPath(); } return FileStorageConfiguration.getPath(caseId, getStringId(), this.getValue().getValue().getName()); @@ -55,11 +49,10 @@ public String getFilePreviewPath(String caseId) { public FileField clone() { FileField clone = new FileField(); super.clone(clone); - clone.remote = this.remote; return clone; } public boolean isRemote() { - return this.remote != null && this.remote; + return "true".equals(getProperties().get("remote")); } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/FileListField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/FileListField.java index 110ba7dc867..98f3e7b196b 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/FileListField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/FileListField.java @@ -11,7 +11,6 @@ @Data public class FileListField extends Field<FileListFieldValue> { - private Boolean remote; public FileListField() { super(); @@ -27,19 +26,6 @@ public void setValue(String value) { this.setRawValue(FileListFieldValue.fromString(value)); } - @Override - public void setDefaultValue(FileListFieldValue defaultValue) { - super.setDefaultValue(defaultValue); - } - - public void setDefaultValue(String defaultValue) { - this.setDefaultValue(FileListFieldValue.fromString(defaultValue)); - } - - public void setDefaultValue(List<String> defaultValues) { - this.setDefaultValue(FileListFieldValue.fromList(defaultValues)); - } - public void addValue(String fileName, String path) { if (this.getRawValue() == null || this.getRawValue().getNamesPaths() == null) { this.setRawValue(new FileListFieldValue()); @@ -59,29 +45,21 @@ public void addValue(String fileName, String path) { * @return path to the saved file */ public String getFilePath(String caseId, String name) { - if (this.remote) { + if (this.isRemote()) { Optional<FileFieldValue> first = this.getValue().getValue().getNamesPaths().stream().filter(fileFieldValue -> fileFieldValue.getName().equals(name)).findFirst(); - if (first.isEmpty()) { - return null; - } - return first.get().getPath(); + return first.map(FileFieldValue::getPath).orElse(null); } return FileStorageConfiguration.getPath(caseId, getStringId(), name); } public boolean isRemote() { - return this.remote; - } - - public void setRemote(boolean remote) { - this.remote = remote; + return "true".equals(getProperties().get("remote")); } @Override public FileListField clone() { FileListField clone = new FileListField(); super.clone(clone); - clone.remote = this.remote; return clone; } } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/MapOptionsField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/MapOptionsField.java index 14c855b0a92..6a91b668777 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/MapOptionsField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/MapOptionsField.java @@ -5,22 +5,15 @@ import lombok.NoArgsConstructor; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; @Data @NoArgsConstructor public abstract class MapOptionsField<T, U> extends Field<U> { - protected Map<String, T> options; - protected Expression optionsExpression; - - public Expression getExpression() { - return optionsExpression; - } - - public void setExpression(Expression choicesExpression) { - this.optionsExpression = choicesExpression; - } + protected LinkedHashMap<String, T> options; + protected Expression<Map<String, T>> optionsExpression; public boolean isDynamic() { return this.optionsExpression != null; diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/MultichoiceField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/MultichoiceField.java index 9faf615a7ef..d73d3b0759f 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/MultichoiceField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/MultichoiceField.java @@ -7,16 +7,16 @@ import lombok.Data; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @Data -public class MultichoiceField extends ChoiceField<Set<I18nString>> { +public class MultichoiceField extends ChoiceField<LinkedHashSet<I18nString>> { public MultichoiceField() { super(); - super.setRawValue(new HashSet<>()); - super.setDefaultValue(new HashSet<>()); + super.setRawValue(new LinkedHashSet<>()); } public MultichoiceField(List<I18nString> values) { diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/NumberField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/NumberField.java index 157c73bac35..66e561c241a 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/NumberField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/NumberField.java @@ -1,18 +1,16 @@ package com.netgrif.application.engine.petrinet.domain.dataset; import com.netgrif.application.engine.importer.model.DataType; -import com.netgrif.application.engine.petrinet.domain.arcs.reference.Referencable; import com.querydsl.core.annotations.PropertyType; import com.querydsl.core.annotations.QueryType; import lombok.Data; @Data //TODO release/8.0.0 @Document? -public class NumberField extends Field<Double> implements Referencable { +public class NumberField extends Field<Double> { public NumberField() { super(); - super.setDefaultValue(0.0d); } @Override @@ -27,13 +25,4 @@ public NumberField clone() { super.clone(clone); return clone; } - - @Override - public int getMultiplicity() { - Double value = this.getRawValue(); - if (value == null) { - return -1; - } - return value.intValue(); - } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/TaskField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/TaskField.java index 35657ff3657..7b6f2e63ca3 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/TaskField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/TaskField.java @@ -5,7 +5,7 @@ import com.querydsl.core.annotations.QueryType; import lombok.Data; -import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; @Data @@ -13,7 +13,6 @@ public class TaskField extends Field<List<String>> { public TaskField() { super(); - this.defaultValue = new ArrayList<>(); } @Override diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/TextField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/TextField.java index 921d89b5955..0db5f6f5612 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/TextField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/TextField.java @@ -1,7 +1,5 @@ package com.netgrif.application.engine.petrinet.domain.dataset; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import com.fasterxml.jackson.annotation.JsonTypeName; import com.netgrif.application.engine.importer.model.DataType; import com.querydsl.core.annotations.PropertyType; import com.querydsl.core.annotations.QueryType; @@ -14,6 +12,11 @@ public TextField() { super(); } + public TextField(String value) { + this(); + setRawValue(value); + } + @Override @QueryType(PropertyType.NONE) public DataType getType() { diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserField.java index 1b62a9551f5..e0ef56a0650 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserField.java @@ -5,26 +5,21 @@ import com.querydsl.core.annotations.PropertyType; import com.querydsl.core.annotations.QueryType; import lombok.Data; -import lombok.Getter; +import lombok.EqualsAndHashCode; -import java.util.Arrays; import java.util.HashSet; import java.util.Set; @Data -public class UserField extends Field<UserFieldValue> { - - private Set<String> roles; +@EqualsAndHashCode(callSuper = true) +public class UserField extends FieldWithAllowedRoles<UserFieldValue> { public UserField() { this(new HashSet<>()); } public UserField(Set<String> values) { - super(); - if (values != null) { - this.roles = values; - } + super(values); } @Override @@ -37,7 +32,6 @@ public DataType getType() { public UserField clone() { UserField clone = new UserField(); super.clone(clone); - clone.roles = this.roles; return clone; } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserFieldValue.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserFieldValue.java index ff3e58e76c3..265eeb905a2 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserFieldValue.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserFieldValue.java @@ -1,9 +1,8 @@ package com.netgrif.application.engine.petrinet.domain.dataset; -import com.netgrif.application.engine.auth.domain.IUser; +import com.netgrif.application.engine.authorization.domain.User; import lombok.AllArgsConstructor; import lombok.Data; -import lombok.Getter; import lombok.NoArgsConstructor; // TODO: release/8.0.0 remove, store only ObjectId @@ -13,19 +12,19 @@ public class UserFieldValue { private String id; - private String name; - private String surname; + private String firstname; + private String lastname; private String email; - public UserFieldValue(IUser user) { + public UserFieldValue(User user) { this.id = user.getStringId(); - this.name = user.getName(); - this.surname = user.getSurname(); + this.firstname = user.getFirstname(); + this.lastname = user.getLastname(); this.email = user.getEmail(); } public String getFullName() { - return name + " " + surname; + return String.join(" ", firstname, lastname); } @Override diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserListField.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserListField.java index ef5eadc49aa..f7f2e79e8c1 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserListField.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserListField.java @@ -3,11 +3,12 @@ import com.netgrif.application.engine.importer.model.DataType; import com.querydsl.core.annotations.PropertyType; import com.querydsl.core.annotations.QueryType; +import lombok.Data; +import lombok.EqualsAndHashCode; -import java.util.ArrayList; -import java.util.List; - -public class UserListField extends Field<UserListFieldValue> { +@Data +@EqualsAndHashCode(callSuper = true) +public class UserListField extends FieldWithAllowedRoles<UserListFieldValue> { public UserListField() { super(); diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserListFieldValue.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserListFieldValue.java index 320ebf73b3e..1212d861263 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserListFieldValue.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/UserListFieldValue.java @@ -1,33 +1,24 @@ package com.netgrif.application.engine.petrinet.domain.dataset; import lombok.Data; +import lombok.NoArgsConstructor; -import java.util.*; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; @Data +@NoArgsConstructor public class UserListFieldValue { private LinkedHashSet<UserFieldValue> userValues; - public UserListFieldValue() { - this.userValues = new LinkedHashSet<>(); - } - public UserListFieldValue(Collection<UserFieldValue> userValues) { - this(); this.userValues = new LinkedHashSet<>(userValues); } - public UserListFieldValue(UserFieldValue userValue) { - this(Set.of(userValue)); - } - - public LinkedHashSet<UserFieldValue> getUserValues() { - return userValues; - } - - public void setUserValues(Collection<UserFieldValue> userValues) { - this.userValues = new LinkedHashSet<>(userValues); + public UserListFieldValue(UserFieldValue actorValue) { + this(Set.of(actorValue)); } @Override diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/Validation.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/Validation.java index 4b672333e0e..f6c4f757a5f 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/Validation.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/Validation.java @@ -1,26 +1,39 @@ package com.netgrif.application.engine.petrinet.domain.dataset; import com.netgrif.application.engine.petrinet.domain.I18nString; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; import lombok.AllArgsConstructor; import lombok.Data; -import lombok.NoArgsConstructor; import java.io.Serializable; +import java.util.ArrayList; @Data -@NoArgsConstructor @AllArgsConstructor public class Validation implements Serializable { private static final long serialVersionUID = 3287600522204188694L; - protected String rule; + protected String name; + private Arguments clientArguments; + private Arguments serverArguments; private I18nString message; + public Validation() { + this.clientArguments = new Arguments(); + this.serverArguments = new Arguments(); + } + @Override public Validation clone() { Validation cloned = new Validation(); - cloned.setRule(rule); + cloned.setName(name); + if (clientArguments != null) { + cloned.setClientArguments(clientArguments.clone()); + } + if (serverArguments != null) { + cloned.setServerArguments(serverArguments.clone()); + } if (this.message != null) { cloned.setMessage(this.message.clone()); } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/Expression.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/Expression.java index 86417bf911c..74484a9d995 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/Expression.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/Expression.java @@ -1,23 +1,37 @@ package com.netgrif.application.engine.petrinet.domain.dataset.logic; import lombok.Data; +import lombok.NoArgsConstructor; import org.bson.types.ObjectId; import java.io.Serializable; @Data -public class Expression implements Serializable { +@NoArgsConstructor +public class Expression<T> implements Serializable { private static final long serialVersionUID = 3687481111847498422L; private String id; + private T defaultValue; private String definition; - private boolean dynamic; - public Expression(String definition, boolean dynamic) { + protected Expression(T defaultValue, String definition) { this.id = new ObjectId().toString(); + this.defaultValue = defaultValue; this.definition = definition; - this.dynamic = dynamic; + } + + public static <T> Expression<T> ofStatic(T defaultValue) { + return new Expression<>(defaultValue, null); + } + + public static <T> Expression<T> ofDynamic(String definition) { + return new Expression<>(null, definition); + } + + public boolean isDynamic() { + return defaultValue == null && definition != null; } @Override @@ -26,7 +40,11 @@ public String toString() { } @Override - public Expression clone() { - return new Expression(this.definition, this.dynamic); + public Expression<T> clone() { + // todo: release/8.0.0 clone defaultValue + if (defaultValue != null) { + return Expression.ofStatic(defaultValue); + } + return Expression.ofDynamic(definition); } } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/FieldBehavior.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/FieldBehavior.java index 1b3c977ba95..d28e2c06d9b 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/FieldBehavior.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/FieldBehavior.java @@ -18,11 +18,12 @@ public boolean isDisplayable() { return this == EDITABLE || this == VISIBLE || this == HIDDEN; } - public static FieldBehavior fromString(Behavior string) { - if (string == null) { + // TODO: release/8.0.0 replace FieldBehavior with importer Behavior + public static FieldBehavior fromXml(Behavior xmlBehavior) { + if (xmlBehavior == null) { throw new IllegalArgumentException("Behavior can not be null"); } - return valueOf(string.value().toUpperCase()); + return valueOf(xmlBehavior.value().toUpperCase()); } @Override diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/FieldLayout.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/FieldLayout.java deleted file mode 100644 index 5173cbf2b4e..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/FieldLayout.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.dataset.logic; - -import com.netgrif.application.engine.petrinet.domain.layout.Layout; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -public class FieldLayout extends Layout { - private int x; - private int y; - private int offset; - private String template; - private String appearance; - private String alignment; - - public FieldLayout(Integer x, Integer y, Integer rows, Integer cols, Integer offset, String template, String appearance, String alignment) { - super(rows, cols); - this.x = nullToZero(x); - this.y = nullToZero(y); - this.offset = nullToZero(offset); - this.template = template.toLowerCase(); - this.appearance = appearance.toLowerCase(); - this.alignment = alignment; - } - - private int nullToZero(Integer i) { - return i != null ? i : 0; - } - - public FieldLayout clone() { - return new FieldLayout(this.x, this.getY(), this.getRows(), this.getCols(), this.getOffset(), this.getTemplate(), this.getAppearance(), this.getAlignment()); - } - - public boolean isLayoutFilled() { - return (this.rows != null - || this.cols != null - || this.x != 0 - || this.y != 0 - || this.offset != 0 - || this.template != null - || this.appearance != null - || this.alignment != null); - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/Action.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/Action.java index faa227cc8a4..0f5f93d8949 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/Action.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/Action.java @@ -1,76 +1,35 @@ package com.netgrif.application.engine.petrinet.domain.dataset.logic.action; -import com.netgrif.application.engine.importer.model.DataEventType; import lombok.Data; +import lombok.NoArgsConstructor; import org.bson.types.ObjectId; import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; @Data +@NoArgsConstructor public class Action implements Serializable { private static final long serialVersionUID = 3687481049847555522L; private String importId; private ObjectId id = new ObjectId(); - // TODO: release/8.0.0 remove both maps, deprecated - private Map<String, String> fieldIds = new HashMap<>(); - private Map<String, String> transitionIds = new HashMap<>(); private String definition; - private DataEventType trigger; // TODO: release/8.0.0 replace with set action type private SetDataType setDataType = SetDataType.VALUE; - public Action(Map<String, String> fieldIds, Map<String, String> transitionIds, String definition, String trigger) { - this(fieldIds, transitionIds, definition, DataEventType.fromValue(trigger)); - } - - public Action(String definition, String trigger) { - this(new HashMap<>(), new HashMap<>(), definition, trigger); - } - - public Action(Map<String, String> fieldIds, Map<String, String> transitionIds, String definition, DataEventType trigger) { - this.definition = definition; - this.trigger = trigger; - this.fieldIds = fieldIds; - this.transitionIds = transitionIds; - } - - public Action() { - } - - public Action(String trigger) { - this.trigger = DataEventType.fromValue(trigger); - } - - public boolean isTriggeredBy(DataEventType trigger) { - return this.trigger == trigger; - } - - public void addFieldId(String fieldName, String fieldId) { - this.fieldIds.put(fieldName, fieldId); - } - - public void addTransitionId(String transitionName, String transitionId) { - this.transitionIds.put(transitionName, transitionId); - } - @Override public String toString() { - return String.format("[%s] %s", trigger, definition); + return definition; } @Override public Action clone() { Action clone = new Action(); clone.setId(new ObjectId(this.getId().toString())); - clone.setTrigger(this.trigger); clone.setDefinition(this.definition); clone.setImportId(this.importId); - clone.setTransitionIds(new HashMap<String, String>(this.transitionIds)); - clone.setFieldIds(new HashMap<String, String>(this.fieldIds)); + clone.setSetDataType(this.setDataType); return clone; } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/events/BaseEvent.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/events/BaseEvent.java index 857e0eb63a2..d9edf164348 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/events/BaseEvent.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/events/BaseEvent.java @@ -5,7 +5,7 @@ import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; import lombok.Data; -import java.util.List; +import java.util.*; @Data public class BaseEvent extends Imported { @@ -16,7 +16,9 @@ public class BaseEvent extends Imported { private I18nString message; - private List<Action> preActions; + private List<Action> preActions = new LinkedList<>(); - private List<Action> postActions; + private List<Action> postActions = new LinkedList<>(); + + private Map<String, String> properties = new LinkedHashMap<>(); } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/events/RoleEvent.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/events/RoleEvent.java new file mode 100644 index 00000000000..477479f7463 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/events/RoleEvent.java @@ -0,0 +1,27 @@ +package com.netgrif.application.engine.petrinet.domain.events; + +import com.netgrif.application.engine.importer.model.RoleEventType; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.stream.Collectors; + +@Data +@EqualsAndHashCode(callSuper = true) +public class RoleEvent extends BaseEvent { + + private RoleEventType type; + + @Override + public RoleEvent clone() { + RoleEvent clone = new RoleEvent(); + clone.setId(this.getId()); + clone.setTitle(this.getTitle() == null ? null : this.getTitle().clone()); + clone.setMessage(this.getMessage() == null ? null : this.getMessage().clone()); + clone.setPreActions(this.getPreActions() == null ? null : getPreActions().stream().map(Action::clone).collect(Collectors.toList())); + clone.setPostActions(this.getPostActions() == null ? null : getPostActions().stream().map(Action::clone).collect(Collectors.toList())); + clone.setType(this.type); + return clone; + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/DataGroupLayout.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/DataGroupLayout.java deleted file mode 100644 index 0d3d69102ad..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/DataGroupLayout.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.layout; - -import com.netgrif.application.engine.importer.model.CompactDirection; -import com.netgrif.application.engine.importer.model.HideEmptyRows; -import com.netgrif.application.engine.importer.model.LayoutType; -import lombok.Data; -import com.netgrif.application.engine.importer.model.DataGroup; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -public class DataGroupLayout extends FormLayout { - - public DataGroupLayout(Integer rows, Integer cols, LayoutType type, HideEmptyRows hideEmptyRows, CompactDirection compactDirection) { - super(rows, cols, type, hideEmptyRows, compactDirection); - } - - public DataGroupLayout(DataGroup data) { - super( - data.getRows(), - data.getCols(), - data.getLayout() != null ? data.getLayout() : null, - data.getHideEmptyRows() != null ? data.getHideEmptyRows() : null, - data.getCompactDirection() != null ? data.getCompactDirection() : null - ); - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/FormLayout.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/FormLayout.java deleted file mode 100644 index 6280c57fd92..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/FormLayout.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.layout; - -import com.netgrif.application.engine.importer.model.CompactDirection; -import com.netgrif.application.engine.importer.model.HideEmptyRows; -import com.netgrif.application.engine.importer.model.LayoutType; -import com.querydsl.core.annotations.PropertyType; -import com.querydsl.core.annotations.QueryType; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -public abstract class FormLayout extends Layout { - // TODO: release/8.0.0 clean up querydsl annotations - @QueryType(PropertyType.NONE) - private LayoutType type; - @QueryType(PropertyType.NONE) - private HideEmptyRows hideEmptyRows; - @QueryType(PropertyType.NONE) - private CompactDirection compactDirection; - - public FormLayout(Integer rows, Integer cols, LayoutType type, HideEmptyRows hideEmptyRows, CompactDirection compactDirection) { - super(rows, cols); - this.type = type; - this.hideEmptyRows = hideEmptyRows; - this.compactDirection = compactDirection; - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/Layout.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/Layout.java deleted file mode 100644 index d77075be582..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/Layout.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.layout; - -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.io.Serializable; - -@Data -@NoArgsConstructor -public abstract class Layout implements Serializable { - - private static final long serialVersionUID = -1177510908437276099L; - - protected Integer rows; - protected Integer cols; - - public Layout(Integer rows, Integer cols) { - this.rows = rows == null || rows == 0 ? null : rows; - this.cols = cols == null || cols == 0 ? null : cols; - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/LayoutContainer.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/LayoutContainer.java new file mode 100644 index 00000000000..beaa10078fc --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/LayoutContainer.java @@ -0,0 +1,55 @@ +package com.netgrif.application.engine.petrinet.domain.layout; + +import com.netgrif.application.engine.petrinet.domain.ProcessObject; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.springframework.data.annotation.Transient; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Data +@AllArgsConstructor +public class LayoutContainer extends ProcessObject { + + private LayoutObjectType layoutType; + + private List<LayoutItem> items; + + private Map<String, String> properties; + + @Transient + private String parentTaskId; + + @Transient + private String parentTransitionId; + + @Transient + private String parentCaseId; + + public LayoutContainer() { + this.items = new LinkedList<>(); + this.properties = new HashMap<>(); + } + + public LayoutContainer(LayoutObjectType layoutType) { + this(); + this.layoutType = layoutType; + } + + public void addLayoutItem(LayoutItem layoutItem) { + this.items.add(layoutItem); + } + + @Override + public LayoutContainer clone() { + LayoutContainer clone = new LayoutContainer(); + clone.setLayoutType(this.layoutType); + clone.setItems(this.items == null ? null : this.items.stream().map(LayoutItem::clone).collect(Collectors.toList())); + clone.setProperties(new HashMap<>(this.properties)); + return clone; + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/LayoutItem.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/LayoutItem.java new file mode 100644 index 00000000000..4c738a11e57 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/LayoutItem.java @@ -0,0 +1,40 @@ +package com.netgrif.application.engine.petrinet.domain.layout; + +import com.netgrif.application.engine.petrinet.domain.DataRef; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.springframework.data.annotation.Transient; + +import java.util.HashMap; +import java.util.Map; + +@Data +@AllArgsConstructor +public class LayoutItem { + + private LayoutObjectType layoutType; + + private String dataRefId; + + @Transient + private DataRef dataRef; + + private LayoutContainer container; + + private Map<String, String> properties; + + public LayoutItem() { + this.properties = new HashMap<>(); + } + + @Override + public LayoutItem clone() { + LayoutItem clone = new LayoutItem(); + clone.setLayoutType(this.layoutType); + clone.setContainer(this.container != null ? this.container.clone() : null); + clone.setDataRefId(this.dataRefId); + clone.setDataRef(this.dataRef == null ? null : this.dataRef.clone()); + clone.setProperties(new HashMap<>(this.properties)); + return clone; + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/LayoutObjectType.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/LayoutObjectType.java new file mode 100644 index 00000000000..4b7525ae6d4 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/LayoutObjectType.java @@ -0,0 +1,25 @@ +package com.netgrif.application.engine.petrinet.domain.layout; + +public enum LayoutObjectType { + FLEX("flex"), + GRID("grid"); + + private final String value; + + LayoutObjectType(String v) { + value = v; + } + + public static LayoutObjectType fromValue(String v) { + for (LayoutObjectType c : LayoutObjectType.values()) { + if (c.value.equals(v)) { + return c; + } + } + throw new IllegalArgumentException(v); + } + + public String value() { + return value; + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/LayoutTypeConverter.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/LayoutTypeConverter.java deleted file mode 100644 index eb17a9400d3..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/LayoutTypeConverter.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.layout; - -import com.netgrif.application.engine.importer.model.LayoutType; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.convert.converter.Converter; -import org.springframework.data.convert.ReadingConverter; -import org.springframework.stereotype.Component; - -@Slf4j -@Component -@ReadingConverter -public class LayoutTypeConverter implements Converter<String, LayoutType> { - - @Override - public LayoutType convert(String source) { - if (source.isBlank()) { - return null; - } - return LayoutType.fromValue(source.toLowerCase()); - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/TaskLayout.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/TaskLayout.java deleted file mode 100644 index 08c7a534bd5..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/layout/TaskLayout.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.layout; - -import com.netgrif.application.engine.importer.model.FieldAlignment; -import com.netgrif.application.engine.importer.model.Transition; -import com.querydsl.core.annotations.PropertyType; -import com.querydsl.core.annotations.QueryType; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class TaskLayout extends FormLayout { - - private Integer offset; - @QueryType(PropertyType.NONE) - private FieldAlignment fieldAlignment; - - public TaskLayout(Transition data) { - super( - data.getLayout().getRows(), - data.getLayout().getCols(), - data.getLayout().getType() != null ? data.getLayout().getType() : null, - data.getLayout().getHideEmptyRows() != null ? data.getLayout().getHideEmptyRows() : null, - data.getLayout().getCompactDirection() != null ? data.getLayout().getCompactDirection() : null - ); - this.offset = data.getLayout().getOffset(); - this.fieldAlignment = data.getLayout().getFieldAlignment() != null ? data.getLayout().getFieldAlignment() : null; - } - - @Override - public TaskLayout clone() { - TaskLayout clone = new TaskLayout(); - clone.setCols(this.getCols()); - clone.setRows(this.getRows()); - clone.setType(this.getType()); - clone.setOffset(this.offset); - clone.setFieldAlignment(this.fieldAlignment); - clone.setCompactDirection(this.getCompactDirection()); - clone.setHideEmptyRows(this.getHideEmptyRows()); - return clone; - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/params/DeleteProcessParams.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/params/DeleteProcessParams.java new file mode 100644 index 00000000000..1712e3f19e4 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/params/DeleteProcessParams.java @@ -0,0 +1,20 @@ +package com.netgrif.application.engine.petrinet.domain.params; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +@Data +@AllArgsConstructor +@Builder(builderMethodName = "with") +public class DeleteProcessParams { + + private String processId; + @Builder.Default + private boolean isTransactional = false; + + public DeleteProcessParams(String processId) { + this.processId = processId; + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/params/ImportProcessParams.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/params/ImportProcessParams.java new file mode 100644 index 00000000000..0dffc3bece5 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/params/ImportProcessParams.java @@ -0,0 +1,38 @@ +package com.netgrif.application.engine.petrinet.domain.params; + +import com.netgrif.application.engine.petrinet.domain.VersionType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +@Data +@AllArgsConstructor +@Builder(builderMethodName = "with") +public class ImportProcessParams { + + private InputStream xmlFile; + private String uriNodeId; + private VersionType releaseType; + private String authorId; + @Builder.Default + private boolean isTransactional = false; + @Builder.Default + private Map<String, String> params = new HashMap<>(); + + public ImportProcessParams(InputStream xmlFile, VersionType releaseType, String authorId, String uriNodeId) { + this.xmlFile = xmlFile; + this.releaseType = releaseType; + this.authorId = authorId; + this.uriNodeId = uriNodeId; + } + + public ImportProcessParams(InputStream xmlFile, VersionType releaseType, String authorId) { + this.xmlFile = xmlFile; + this.releaseType = releaseType; + this.authorId = authorId; + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java index d1ece252862..c5aee453e46 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java @@ -1,32 +1,36 @@ package com.netgrif.application.engine.petrinet.domain.repositories; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.version.Version; import org.bson.types.ObjectId; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.data.mongodb.repository.Query; import org.springframework.data.querydsl.QuerydslPredicateExecutor; import java.util.List; -public interface PetriNetRepository extends MongoRepository<PetriNet, String>, QuerydslPredicateExecutor<PetriNet> { +public interface PetriNetRepository extends MongoRepository<Process, String>, QuerydslPredicateExecutor<Process> { - List<PetriNet> findByTitle_DefaultValue(String title); + List<Process> findByTitle_DefaultValue(String title); - PetriNet findByImportId(String id); + Process findByImportId(String id); - List<PetriNet> findAllByIdentifier(String identifier); + List<Process> findAllByIdentifier(String identifier); - PetriNet findByIdentifierAndVersion(String identifier, Version version); + Process findByIdentifierAndVersion(String identifier, Version version); - Page<PetriNet> findByIdentifier(String identifier, Pageable pageable); + @Query("{'parentIdentifiers.id' : ?0}") + List<Process> findAllChildrenByParentId(ObjectId id); - Page<PetriNet> findByIdentifierIn(List<String> identifier, Pageable pageable); + Page<Process> findByIdentifier(String identifier, Pageable pageable); - List<PetriNet> findAllByVersion(Version version); + Page<Process> findByIdentifierIn(List<String> identifier, Pageable pageable); - List<PetriNet> findAllByUriNodeId(String uri); + List<Process> findAllByVersion(Version version); + + List<Process> findAllByUriNodeId(String uri); void deleteById(ObjectId id); } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/repository/UriNodeRepository.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/UriNodeRepository.java similarity index 99% rename from src/main/java/com/netgrif/application/engine/petrinet/domain/repository/UriNodeRepository.java rename to src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/UriNodeRepository.java index 4cac3034dc0..050a39c4e09 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/repository/UriNodeRepository.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/UriNodeRepository.java @@ -1,4 +1,4 @@ -package com.netgrif.application.engine.petrinet.domain.repository; +package com.netgrif.application.engine.petrinet.domain.repositories; import com.netgrif.application.engine.petrinet.domain.UriNode; import org.springframework.data.mongodb.repository.MongoRepository; diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/AssignedUserPermission.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/AssignedUserPermission.java deleted file mode 100644 index c717e5417dc..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/AssignedUserPermission.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.roles; - -public enum AssignedUserPermission { - CANCEL, - REASSIGN -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/ProcessRole.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/ProcessRole.java deleted file mode 100755 index a5b37def200..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/ProcessRole.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.roles; - -import com.netgrif.application.engine.importer.model.EventType; -import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.petrinet.domain.Imported; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; -import com.netgrif.application.engine.petrinet.domain.events.Event; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.bson.types.ObjectId; -import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; - -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -@Getter -@Document -@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false) -public class ProcessRole extends Imported { - - public static final String DEFAULT_ROLE = "default"; - - public static final String ANONYMOUS_ROLE = "anonymous"; - - @Id - @Setter - private ObjectId id; - - private I18nString name; - - @Getter - @Setter - private String netId; - - @Setter - private String description; - - @Getter - @Setter - private Map<EventType, Event> events; - - public ProcessRole() { - id = new ObjectId(); - } - - public ProcessRole(String id) { - this.id = new ObjectId(id); - } - - @EqualsAndHashCode.Include - public String getStringId() { - return id.toString(); - } - - public ObjectId getId() { - return id; - } - - public void setId(ObjectId id) { - this.id = id; - } - - public void setId(String id) { - this.id = new ObjectId(id); - } - - public I18nString getName() { - return name; - } - - public void setName(String name) { - setName(new I18nString(name)); - } - - public void setName(I18nString name) { - this.name = name; - } - - public String getLocalisedName(Locale locale) { - if (name == null) - return null; - return name.getTranslation(locale); - } - - public List<Action> getPreAssignActions() { - return getPreActions(EventType.ASSIGN); - } - - public List<Action> getPostAssignActions() { - return getPostActions(EventType.ASSIGN); - } - - public List<Action> getPreCancelActions() { - return getPreActions(EventType.CANCEL); - } - - public List<Action> getPostCancelActions() { - return getPostActions(EventType.CANCEL); - } - - private List<Action> getPreActions(EventType type) { - if (events != null && events.containsKey(type)) - return events.get(type).getPreActions(); - return new LinkedList<>(); - } - - private List<Action> getPostActions(EventType type) { - if (events != null && events.containsKey(type)) - return events.get(type).getPostActions(); - return new LinkedList<>(); - } - - @Override - public String toString() { - return name.getDefaultValue(); - } - - @Override - public ProcessRole clone() { - ProcessRole clone = new ProcessRole(); - clone.setId(this.id); - clone.setImportId(this.importId); - clone.setName(this.name == null ? null : this.name.clone()); - clone.setNetId(this.netId); - clone.setDescription(this.description); - return clone; - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleRepository.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleRepository.java deleted file mode 100755 index 4d4830b6a60..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleRepository.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.roles; - -import org.bson.types.ObjectId; -import org.springframework.data.mongodb.repository.MongoRepository; -import org.springframework.data.querydsl.QuerydslPredicateExecutor; -import org.springframework.stereotype.Repository; - -import java.util.Collection; -import java.util.Set; - -@Repository -public interface ProcessRoleRepository extends MongoRepository<ProcessRole, String>, QuerydslPredicateExecutor<ProcessRole> { - - Set<ProcessRole> findAllByNetId(String netId); - - Set<ProcessRole> findAllByImportIdIn(Set<String> importIds); - - Set<ProcessRole> findAllByName_DefaultValue(String name); - - Set<ProcessRole> findAllByImportId(String importId); - - void deleteAllByIdIn(Collection<ObjectId> ids); -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/RolePermission.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/RolePermission.java deleted file mode 100644 index cc218d95fca..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/roles/RolePermission.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.roles; - - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonValue; - -public enum RolePermission { - DELEGATE, - CANCEL, - ASSIGN, - FINISH, - SET, - VIEW; - - @JsonValue - public String value() { - return super.name().toLowerCase(); - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/throwable/IllegalArcNodeException.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/throwable/IllegalArcNodeException.java new file mode 100644 index 00000000000..1db429f80fb --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/throwable/IllegalArcNodeException.java @@ -0,0 +1,16 @@ +package com.netgrif.application.engine.petrinet.domain.throwable; + +public class IllegalArcNodeException extends RuntimeException { + + public IllegalArcNodeException(String message) { + super(message); + } + + public static IllegalArcNodeException fromTransition(String arcType) { + return new IllegalArcNodeException(arcType + " can not lead from a Transition"); + } + + public static IllegalArcNodeException toPlace(String arcType) { + return new IllegalArcNodeException(arcType + " can not lead to a Place"); + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/throwable/IllegalMarkingException.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/throwable/IllegalMarkingException.java new file mode 100644 index 00000000000..c883defc7fc --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/throwable/IllegalMarkingException.java @@ -0,0 +1,10 @@ +package com.netgrif.application.engine.petrinet.domain.throwable; + +import com.netgrif.application.engine.petrinet.domain.Place; + +public class IllegalMarkingException extends IllegalStateException { + + public IllegalMarkingException(Place place) { + super("Place (" + place.getImportId() + ") can not have negative number of tokens."); + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/domain/version/Version.java b/src/main/java/com/netgrif/application/engine/petrinet/domain/version/Version.java index 463dbc4a0bc..49a3515ce19 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/domain/version/Version.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/domain/version/Version.java @@ -20,25 +20,41 @@ public class Version implements Serializable { public static final String NEWEST = "^"; public static final String LATEST = "latest"; + private static final long serialVersionUID = -4714902376220642455L; + private static final String VERSION_STRING_REGEX = "[0-9]+\\.[0-9]+\\.[0-9]+"; + + private static final String VERSION_DELIMITER = "."; + private long major; private long minor; private long patch; + /** + * Creates version initialized to 1.0.0 + * */ public Version() { major = 1; minor = 0; patch = 0; } + /** + * Example output {@code "1.1.2"} + * */ @Override public String toString() { - return major + "." + minor + "." + patch; + return major + VERSION_DELIMITER + minor + VERSION_DELIMITER + patch; } + /** + * Increments version number corresponding to provided {@link VersionType} + * + * @param type {@link VersionType} of number to be incremented + * */ public void increment(VersionType type) { if (type == MAJOR) { major += 1; @@ -60,4 +76,33 @@ public Version clone() { clone.setPatch(this.patch); return clone; } + + /** + * Compares versions by attributes. + * + * @param o object, that should be instance of {@link Version} + * + * @return true if the provided object is not null, of correct type and matches in attribute numbers + * */ + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + Version compareWith = (Version) o; + return major == compareWith.getMajor() && minor == compareWith.getMinor() && patch == compareWith.getPatch() ; + } + + /** + * Creates new {@link Version} of the provided version string + * + * @param versionString version string by which the {@link Version} is created. Must be in correct format + * ({@link Version#VERSION_STRING_REGEX}) + * */ + public static Version of(String versionString) { + if (versionString == null || !versionString.matches(VERSION_STRING_REGEX)) { + throw new IllegalArgumentException("Version string is invalid"); + } + String[] versionParts = versionString.split(String.format("\\%s", VERSION_DELIMITER)); + return new Version(Integer.parseInt(versionParts[0]), Integer.parseInt(versionParts[1]), + Integer.parseInt(versionParts[2])); + } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/ArcFactory.java b/src/main/java/com/netgrif/application/engine/petrinet/service/ArcFactory.java deleted file mode 100644 index 148023ecc06..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/ArcFactory.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.netgrif.application.engine.petrinet.service; - -import com.netgrif.application.engine.petrinet.domain.arcs.Arc; -import com.netgrif.application.engine.petrinet.domain.arcs.InhibitorArc; -import com.netgrif.application.engine.petrinet.domain.arcs.ReadArc; -import com.netgrif.application.engine.petrinet.domain.arcs.ResetArc; -import com.netgrif.application.engine.petrinet.domain.arcs.reference.Reference; -import com.netgrif.application.engine.petrinet.domain.arcs.reference.Type; -import org.springframework.stereotype.Component; - -@Component -public final class ArcFactory { - - public Arc getArc(com.netgrif.application.engine.importer.model.Arc arc) throws IllegalArgumentException { - switch (arc.getType()) { - case REGULAR: - return new Arc(); - case RESET: - return new ResetArc(); - case INHIBITOR: - return new InhibitorArc(); - case READ: - return new ReadArc(); - case VARIABLE: - Arc varArc = new Arc(); - Reference ref = new Reference(); - ref.setReference(String.valueOf(arc.getMultiplicity())); - varArc.setReference(ref); - return varArc; - default: - throw new IllegalArgumentException(arc.getType() + " is not a valid Arc type"); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/MultiplicityEvaluator.java b/src/main/java/com/netgrif/application/engine/petrinet/service/MultiplicityEvaluator.java new file mode 100644 index 00000000000..68db3ac8892 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/petrinet/service/MultiplicityEvaluator.java @@ -0,0 +1,22 @@ +package com.netgrif.application.engine.petrinet.service; + +import com.netgrif.application.engine.petrinet.domain.arcs.Multiplicity; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ExpressionRunner; +import com.netgrif.application.engine.workflow.domain.Case; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class MultiplicityEvaluator { + + @Autowired + private ExpressionRunner runner; + + public int evaluate(Multiplicity multiplicity, Case useCase) { + Object run = runner.run(multiplicity, useCase); + if (!(run instanceof Integer)) { + throw new IllegalStateException("Multiplicity could not be evaluated"); + } + return (int) run; + } +} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java deleted file mode 100644 index 4cbee55a302..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.netgrif.application.engine.petrinet.service; - -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetAuthorizationService; -import org.springframework.stereotype.Service; - -@Service -public class PetriNetAuthorizationService implements IPetriNetAuthorizationService { - @Override - public boolean canCallProcessDelete(LoggedUser loggedUser, String processId) { - return loggedUser.isAdmin(); - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetEventHandler.java b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetEventHandler.java index cacc8b352f2..46c6f78ed69 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetEventHandler.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetEventHandler.java @@ -1,27 +1,40 @@ package com.netgrif.application.engine.petrinet.service; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetMappingService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetService; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.bson.Document; import org.bson.types.ObjectId; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; import org.springframework.data.mongodb.core.mapping.event.AfterDeleteEvent; +import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent; import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionalEventListener; @Slf4j @Component -public class PetriNetEventHandler extends AbstractMongoEventListener<PetriNet> { +@RequiredArgsConstructor +public class PetriNetEventHandler { - @Autowired - private IElasticPetriNetService service; + private final IElasticPetriNetService service; + private final IElasticPetriNetMappingService petriNetMappingService; - @Override - public void onAfterDelete(AfterDeleteEvent<PetriNet> event) { + @TransactionalEventListener(fallbackExecution = true, condition = "#event.collectionName == 'process'") + public void onAfterSave(AfterSaveEvent<Process> event) { + Process process = event.getSource(); + try { + service.indexNow(petriNetMappingService.transform(process)); + } catch (Exception e) { + log.error("Indexing failed [{}]", process.getStringId(), e); + } + } + + @TransactionalEventListener(fallbackExecution = true, condition = "#event.collectionName == 'process'") + public void onAfterDelete(AfterDeleteEvent<Process> event) { Document document = event.getDocument(); - if (document == null) { - log.warn("Trying to delete null document!"); + if (document == null || document.isEmpty()) { + log.warn("Trying to delete null or empty document!"); return; } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index bb46f0af89a..1a90cb720f9 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -2,8 +2,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.type.TypeFactory; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; import com.netgrif.application.engine.configuration.properties.CacheProperties; import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetMappingService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetService; @@ -12,32 +11,35 @@ import com.netgrif.application.engine.history.domain.taskevents.TaskEventLog; import com.netgrif.application.engine.history.service.IHistoryService; import com.netgrif.application.engine.importer.model.ProcessEventType; +import com.netgrif.application.engine.importer.service.ImportResult; import com.netgrif.application.engine.importer.service.Importer; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; import com.netgrif.application.engine.ldap.service.interfaces.ILdapGroupRefService; -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.petrinet.domain.Transition; -import com.netgrif.application.engine.petrinet.domain.VersionType; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionRunner; import com.netgrif.application.engine.petrinet.domain.events.EventPhase; +import com.netgrif.application.engine.petrinet.domain.params.DeleteProcessParams; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository; import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; import com.netgrif.application.engine.petrinet.domain.version.Version; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; import com.netgrif.application.engine.petrinet.service.interfaces.IUriService; import com.netgrif.application.engine.petrinet.web.responsebodies.*; import com.netgrif.application.engine.rules.domain.facts.NetImportedFact; import com.netgrif.application.engine.rules.service.interfaces.IRuleEngine; +import com.netgrif.application.engine.transaction.NaeTransaction; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.FileStorageConfiguration; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; import com.netgrif.application.engine.workflow.service.interfaces.IEventService; import com.netgrif.application.engine.workflow.service.interfaces.IFieldActionsCacheService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import groovy.lang.Closure; import lombok.extern.slf4j.Slf4j; import org.apache.tomcat.util.http.fileupload.IOUtils; import org.bson.Document; @@ -47,6 +49,7 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.core.io.FileSystemResource; import org.springframework.data.domain.*; +import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationResults; @@ -55,14 +58,13 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionSynchronizationManager; import javax.annotation.Resource; import javax.inject.Provider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Path; import java.util.*; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -74,7 +76,7 @@ public class PetriNetService implements IPetriNetService { @Autowired - private IProcessRoleService processRoleService; + private IRoleService roleService; @Autowired private PetriNetRepository repository; @@ -91,9 +93,6 @@ public class PetriNetService implements IPetriNetService { @Autowired private IWorkflowService workflowService; - @Autowired - private INextGroupService groupService; - @Autowired private Provider<Importer> importerProvider; @@ -106,9 +105,6 @@ public class PetriNetService implements IPetriNetService { @Autowired private IFieldActionsCacheService functionCacheService; - @Autowired - private IUserService userService; - @Autowired private IEventService eventService; @@ -127,11 +123,17 @@ public class PetriNetService implements IPetriNetService { @Autowired private IElasticPetriNetMappingService petriNetMappingService; + @Autowired + private MongoTransactionManager transactionManager; + @Autowired private IUriService uriService; private IElasticPetriNetService elasticPetriNetService; + @Autowired + private ISessionManagerService sessionManagerService; + @Autowired public void setElasticPetriNetService(IElasticPetriNetService elasticPetriNetService) { this.elasticPetriNetService = elasticPetriNetService; @@ -149,7 +151,7 @@ public void evictAllCaches() { requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetByIdentifier()), cacheProperties.getPetriNetByIdentifier()).clear(); } - public void evictCache(PetriNet net) { + public void evictCache(Process net) { requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetById()), cacheProperties.getPetriNetById()).evict(net.getStringId()); requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetNewest()), cacheProperties.getPetriNetNewest()).evict(net.getIdentifier()); requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetCache()), cacheProperties.getPetriNetCache()).evict(net.getObjectId()); @@ -161,8 +163,8 @@ public void evictCache(PetriNet net) { */ @Override @Cacheable(value = "petriNetCache") - public PetriNet get(ObjectId petriNetId) { - Optional<PetriNet> optional = repository.findById(petriNetId.toString()); + public Process get(ObjectId petriNetId) { + Optional<Process> optional = repository.findById(petriNetId.toString()); if (optional.isEmpty()) { throw new IllegalArgumentException("Petri net with id [" + petriNetId + "] not found"); } @@ -170,119 +172,153 @@ public PetriNet get(ObjectId petriNetId) { } @Override - public List<PetriNet> get(Collection<ObjectId> petriNetIds) { + public List<Process> get(Collection<ObjectId> petriNetIds) { return petriNetIds.stream().map(id -> self.get(id)).collect(Collectors.toList()); } @Override - public List<PetriNet> get(List<String> petriNetIds) { + public List<Process> get(List<String> petriNetIds) { return self.get(petriNetIds.stream().map(ObjectId::new).collect(Collectors.toList())); } @Override - public PetriNet clone(ObjectId petriNetId) { + public Process clone(ObjectId petriNetId) { return self.get(petriNetId).clone(); } - @Override - @Deprecated - public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, String releaseType, LoggedUser author) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { - return importPetriNet(xmlFile, VersionType.valueOf(releaseType.trim().toUpperCase()), author, uriService.getRoot().getStringId()); - } - - @Override - @Deprecated - public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, String releaseType, LoggedUser author, String uriNodeId) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { - return importPetriNet(xmlFile, VersionType.valueOf(releaseType.trim().toUpperCase()), author, uriNodeId); - } - - @Override - public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser author) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { - return importPetriNet(xmlFile, releaseType, author, uriService.getRoot().getStringId()); - } - - @Override - public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser author, Map<String, String> params) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { - return importPetriNet(xmlFile, releaseType, author, uriService.getRoot().getStringId(), params); - } - - @Override - public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser author, String uriNodeId) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { - return importPetriNet(xmlFile, releaseType, author, uriNodeId, new HashMap<>()); + /** + * Creates {@link Process} and saves it into database. + * + * @param importProcessParams parameters for PetriNet creation + * <br> + * <b>Required parameters</b> + * <ul> + * <li>xmlFile</li> + * <li>releaseType</li> + * <li>author</li> + * </ul> + * + * @return outcome containing the created PetriNet + * */ + @Override + public ImportPetriNetEventOutcome importProcess(ImportProcessParams importProcessParams) throws IOException, + MissingPetriNetMetaDataException, MissingIconKeyException { + fillMissingAttributes(importProcessParams); + + if (importProcessParams.isTransactional() && !TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<ImportPetriNetEventOutcome>(null) { + @Override + public ImportPetriNetEventOutcome call() { + try { + return doImportPetriNet(importProcessParams); + } catch (MissingPetriNetMetaDataException | IOException e) { + throw new RuntimeException(e); + } + } + }) + .build(); + transaction.begin(); + return (ImportPetriNetEventOutcome) transaction.getResultOfEvent(); + } else { + return doImportPetriNet(importProcessParams); + } } - @Override - public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser author, String uriNodeId, Map<String, String> params) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { + private ImportPetriNetEventOutcome doImportPetriNet(ImportProcessParams importProcessParams) throws MissingPetriNetMetaDataException, IOException { ImportPetriNetEventOutcome outcome = new ImportPetriNetEventOutcome(); ByteArrayOutputStream xmlCopy = new ByteArrayOutputStream(); - IOUtils.copy(xmlFile, xmlCopy); - Optional<PetriNet> imported = getImporter().importPetriNet(new ByteArrayInputStream(xmlCopy.toByteArray())); - if (imported.isEmpty()) { + IOUtils.copy(importProcessParams.getXmlFile(), xmlCopy); + ImportResult imported = getImporter().importPetriNet(new ByteArrayInputStream(xmlCopy.toByteArray())); + if (imported.getProcess() == null) { return outcome; } - PetriNet net = imported.get(); - net.setUriNodeId(uriNodeId); + Process process = imported.getProcess(); + if (ObjectId.isValid(importProcessParams.getUriNodeId())) { + process.setUriNodeId(importProcessParams.getUriNodeId()); + } - // TODO: release/8.0.0 fix cacheable - PetriNet existingNet = getNewestVersionByIdentifier(net.getIdentifier()); + Process existingNet = self.getNewestVersionByIdentifier(process.getIdentifier()); if (existingNet != null) { - net.setVersion(existingNet.getVersion()); - net.incrementVersion(releaseType); + process.setVersion(existingNet.getVersion()); + process.incrementVersion(importProcessParams.getReleaseType()); } - processRoleService.saveAll(net.getRoles().values()); - net.setAuthor(author.transformToAuthor()); - functionCacheService.cachePetriNetFunctions(net); - Path savedPath = getImporter().saveNetFile(net, new ByteArrayInputStream(xmlCopy.toByteArray())); + roleService.saveAll(imported.getRoles().values()); + process.setAuthorId(importProcessParams.getAuthorId()); + functionCacheService.cachePetriNetFunctions(process); + // TODO: release/8.0.0 +// Path savedPath = getImporter().saveNetFile(process, new ByteArrayInputStream(xmlCopy.toByteArray())); xmlCopy.close(); - log.info("Petri net {} ({} v{}) imported successfully and saved in a folder: {}", net.getTitle(), net.getInitials(), net.getVersion(), savedPath.toString()); - - outcome.setOutcomes(eventService.runActions(net.getPreUploadActions(), null, Optional.empty(), params)); - evaluateRules(net, EventPhase.PRE); - historyService.save(new ImportPetriNetEventLog(null, EventPhase.PRE, net.getObjectId())); - save(net); - outcome.setOutcomes(eventService.runActions(net.getPostUploadActions(), null, Optional.empty(), params)); - evaluateRules(net, EventPhase.POST); - historyService.save(new ImportPetriNetEventLog(null, EventPhase.POST, net.getObjectId())); - addMessageToOutcome(net, ProcessEventType.UPLOAD, outcome); - outcome.setNet(imported.get()); +// log.info("Petri net {} ({} v{}) imported successfully and saved in a folder: {}", process.getTitle(), process.getInitials(), process.getVersion(), savedPath.toString()); + + outcome.setOutcomes(eventService.runActions(process.getPreUploadActions(), null, Optional.empty(), + importProcessParams.getParams())); + boolean wasSaved = evaluateRules(process, EventPhase.PRE); + + historyService.save(new ImportPetriNetEventLog(null, EventPhase.PRE, process.getObjectId())); + + if (!wasSaved) { + save(process); + } + + outcome.setOutcomes(eventService.runActions(process.getPostUploadActions(), null, Optional.empty(), + importProcessParams.getParams())); + evaluateRules(process, EventPhase.POST); + + historyService.save(new ImportPetriNetEventLog(null, EventPhase.POST, process.getObjectId())); + + addMessageToOutcome(process, ProcessEventType.UPLOAD, outcome); + outcome.setProcess(imported.getProcess()); return outcome; } - private ImportPetriNetEventOutcome addMessageToOutcome(PetriNet net, ProcessEventType type, ImportPetriNetEventOutcome outcome) { + private void fillMissingAttributes(ImportProcessParams importProcessParams) throws IllegalArgumentException { + if (importProcessParams.getXmlFile() == null) { + throw new IllegalArgumentException("No Petriflow source file provided."); + } + if (importProcessParams.getReleaseType() == null) { + throw new IllegalArgumentException("Version type is null."); + } + if (importProcessParams.getUriNodeId() == null) { + importProcessParams.setUriNodeId(uriService.getRoot().getStringId()); + } + } + + private ImportPetriNetEventOutcome addMessageToOutcome(Process net, ProcessEventType type, ImportPetriNetEventOutcome outcome) { if (net.getProcessEvents().containsKey(type)) { outcome.setMessage(net.getProcessEvents().get(type).getMessage()); } return outcome; } - protected void evaluateRules(PetriNet net, EventPhase phase) { + /** + * @return true if the net was saved + * */ + private boolean evaluateRules(Process net, EventPhase phase) { int rulesExecuted = ruleEngine.evaluateRules(net, new NetImportedFact(net.getStringId(), phase)); if (rulesExecuted > 0) { save(net); + return true; } + return false; } @Override - public Optional<PetriNet> save(PetriNet petriNet) { + public Optional<Process> save(Process petriNet) { petriNet.initializeArcs(); this.evictCache(petriNet); petriNet = repository.save(petriNet); - try { - elasticPetriNetService.indexNow(this.petriNetMappingService.transform(petriNet)); - } catch (Exception e) { - log.error("Indexing failed [{}]", petriNet.getStringId(), e); - } - return Optional.of(petriNet); } @Override @Cacheable(value = "petriNetById") - public PetriNet getPetriNet(String id) { - Optional<PetriNet> net = repository.findById(id); + public Process getPetriNet(String id) { + Optional<Process> net = repository.findById(id); if (net.isEmpty()) { - throw new IllegalArgumentException("No Petri net with id: " + id + " was found."); + throw new IllegalArgumentException("No process with id [" + id + "] was found."); } net.get().initializeArcs(); return net.get(); @@ -290,8 +326,8 @@ public PetriNet getPetriNet(String id) { @Override @Cacheable(value = "petriNetByIdentifier", key = "#identifier+#version.toString()", unless = "#result == null") - public PetriNet getPetriNet(String identifier, Version version) { - PetriNet net = repository.findByIdentifierAndVersion(identifier, version); + public Process getPetriNet(String identifier, Version version) { + Process net = repository.findByIdentifierAndVersion(identifier, version); if (net == null) { return null; } @@ -300,28 +336,28 @@ public PetriNet getPetriNet(String identifier, Version version) { } @Override - public List<PetriNet> getByIdentifier(String identifier) { - List<PetriNet> nets = repository.findAllByIdentifier(identifier); - nets.forEach(PetriNet::initializeArcs); + public List<Process> getByIdentifier(String identifier) { + List<Process> nets = repository.findAllByIdentifier(identifier); + nets.forEach(Process::initializeArcs); return nets; } @Override - public List<PetriNet> findAllByUriNodeId(String uriNodeId) { - List<PetriNet> nets = elasticPetriNetService.findAllByUriNodeId(uriNodeId); - nets.forEach(PetriNet::initializeArcs); + public List<Process> findAllByUriNodeId(String uriNodeId) { + List<Process> nets = elasticPetriNetService.findAllByUriNodeId(uriNodeId); + nets.forEach(Process::initializeArcs); return nets; } @Override - public List<PetriNet> findAllById(List<String> ids) { + public List<Process> findAllById(List<String> ids) { return StreamSupport.stream(repository.findAllById(ids).spliterator(), false).collect(Collectors.toList()); } @Override @Cacheable(value = "petriNetNewest", unless = "#result == null") - public PetriNet getNewestVersionByIdentifier(String identifier) { - List<PetriNet> nets = repository.findByIdentifier(identifier, PageRequest.of(0, 1, Sort.Direction.DESC, "version.major", "version.minor", "version.patch")).getContent(); + public Process getNewestVersionByIdentifier(String identifier) { + List<Process> nets = repository.findByIdentifier(identifier, PageRequest.of(0, 1, Sort.Direction.DESC, "version.major", "version.minor", "version.patch")).getContent(); if (nets.isEmpty()) { return null; } @@ -329,7 +365,7 @@ public PetriNet getNewestVersionByIdentifier(String identifier) { } /** - * Determines which of the provided Strings are identifiers of {@link PetriNet}s uploaded in the system. + * Determines which of the provided Strings are identifiers of {@link Process}s uploaded in the system. * * @param identifiers a list of Strings that represent potential PetriNet identifiers * @return a list containing a subset of the input strings that correspond to identifiers of PetriNets that are present in the system @@ -343,7 +379,7 @@ public List<String> getExistingPetriNetIdentifiersFromIdentifiersList(List<Strin ); AggregationResults<?> groupResults = mongoTemplate.aggregate( agg, - PetriNet.class, + Process.class, TypeFactory.defaultInstance().constructType(new TypeReference<Map<String, String>>() { }).getRawClass() ); @@ -356,11 +392,12 @@ public List<String> getExistingPetriNetIdentifiersFromIdentifiersList(List<Strin public PetriNetImportReference getNetFromCase(String caseId) { Case useCase = workflowService.findOne(caseId); PetriNetImportReference pn = new PetriNetImportReference(); - useCase.getPetriNet().getTransitions().forEach((key, value) -> pn.getTransitions().add(new TransitionImportReference(value))); - useCase.getPetriNet().getPlaces().forEach((key, value) -> pn.getPlaces().add(new PlaceImportReference(value))); - useCase.getPetriNet().getArcs().forEach((key, arcs) -> { - arcs.forEach(arc -> pn.getArcs().add(new ArcImportReference(arc))); - }); + useCase.getProcess().getTransitions().forEach((key, value) -> pn.getTransitions().add(new TransitionImportReference(value))); + useCase.getProcess().getPlaces().forEach((key, value) -> pn.getPlaces().add(new PlaceImportReference(value))); + // TODO: release/8.0.0 needed? +// useCase.getProcess().getArcs().forEach((key, arcs) -> { +// arcs.forEach(arc -> pn.getArcs().add(new ArcImportReference(arc))); +// }); pn.getAssignedTasks().addAll(historyService.findAllAssignTaskEventLogsByCaseId(caseId) .stream().map(TaskEventLog::getTransitionId).filter(Objects::nonNull).distinct().collect(Collectors.toList())); pn.getFinishedTasks().addAll(historyService.findAllFinishTaskEventLogsByCaseId(caseId) @@ -369,9 +406,9 @@ public PetriNetImportReference getNetFromCase(String caseId) { } @Override - public List<PetriNet> getAll() { - List<PetriNet> nets = repository.findAll(); - nets.forEach(PetriNet::initializeArcs); + public List<Process> getAll() { + List<Process> nets = repository.findAll(); + nets.forEach(Process::initializeArcs); return nets; } @@ -380,7 +417,7 @@ public FileSystemResource getFile(String netId, String title) { if (title == null || title.isEmpty()) { Query query = Query.query(Criteria.where("id").is(new ObjectId(netId))); query.fields().include("id").include("title"); - List<PetriNet> nets = mongoTemplate.find(query, PetriNet.class); + List<Process> nets = mongoTemplate.find(query, Process.class); if (nets.isEmpty()) return null; title = nets.get(0).getTitle().getDefaultValue(); @@ -389,17 +426,17 @@ public FileSystemResource getFile(String netId, String title) { } @Override - public List<PetriNetReference> getReferences(LoggedUser user, Locale locale) { + public List<PetriNetReference> getReferences(Locale locale) { return getAll().stream().map(net -> transformToReference(net, locale)).collect(Collectors.toList()); } @Override - public List<PetriNetReference> getReferencesByIdentifier(String identifier, LoggedUser user, Locale locale) { + public List<PetriNetReference> getReferencesByIdentifier(String identifier, Locale locale) { return getByIdentifier(identifier).stream().map(net -> transformToReference(net, locale)).collect(Collectors.toList()); } @Override - public List<PetriNetReference> getReferencesByVersion(Version version, LoggedUser user, Locale locale) { + public List<PetriNetReference> getReferencesByVersion(Version version, Locale locale) { List<PetriNetReference> references; if (version == null) { @@ -410,7 +447,7 @@ public List<PetriNetReference> getReferencesByVersion(Version version, LoggedUse .map(doc -> { Document versionDoc = doc.get("version", Document.class); Version refVersion = new Version(versionDoc.getLong("major"), versionDoc.getLong("minor"), versionDoc.getLong("patch")); - return getReference(doc.getString("_id"), refVersion, user, locale); + return getReference(doc.getString("_id"), refVersion, locale); }) .collect(Collectors.toList()); } else { @@ -422,20 +459,14 @@ public List<PetriNetReference> getReferencesByVersion(Version version, LoggedUse } @Override - public List<PetriNetReference> getReferencesByUsersProcessRoles(LoggedUser user, Locale locale) { - Query query = Query.query(getProcessRolesCriteria(user)); - return mongoTemplate.find(query, PetriNet.class).stream().map(net -> transformToReference(net, locale)).collect(Collectors.toList()); - } - - @Override - public PetriNetReference getReference(String identifier, Version version, LoggedUser user, Locale locale) { - PetriNet net = version == null ? getNewestVersionByIdentifier(identifier) : getPetriNet(identifier, version); + public PetriNetReference getReference(String identifier, Version version, Locale locale) { + Process net = version == null ? getNewestVersionByIdentifier(identifier) : getPetriNet(identifier, version); return net != null ? transformToReference(net, locale) : new PetriNetReference(); } @Override - public List<TransitionReference> getTransitionReferences(List<String> netIds, LoggedUser user, Locale locale) { - Iterable<PetriNet> nets = get(netIds); + public List<TransitionReference> getTransitionReferences(List<String> netIds, Locale locale) { + Iterable<Process> nets = get(netIds); List<TransitionReference> references = new ArrayList<>(); nets.forEach(net -> references.addAll(net.getTransitions().entrySet().stream() @@ -446,7 +477,7 @@ public List<TransitionReference> getTransitionReferences(List<String> netIds, Lo @Override public List<DataFieldReference> getDataFieldReferences(List<TransitionReference> transitions, Locale locale) { - Iterable<PetriNet> nets = repository.findAllById(transitions.stream().map(TransitionReference::getPetriNetId).collect(Collectors.toList())); + Iterable<Process> nets = repository.findAllById(transitions.stream().map(TransitionReference::getPetriNetId).collect(Collectors.toList())); List<DataFieldReference> dataRefs = new ArrayList<>(); Map<String, List<TransitionReference>> transitionReferenceMap = transitions.stream() .collect(Collectors.groupingBy(TransitionReference::getPetriNetId)); @@ -465,18 +496,15 @@ public List<DataFieldReference> getDataFieldReferences(List<TransitionReference> } @Override - public Optional<PetriNet> findByImportId(String id) { - return Optional.of(repository.findByImportId(id)); + public Optional<Process> findByImportId(String id) { + return Optional.ofNullable(repository.findByImportId(id)); } @Override - public Page<PetriNetReference> search(PetriNetSearch criteriaClass, LoggedUser user, Pageable pageable, Locale locale) { + public Page<PetriNetReference> search(PetriNetSearch criteriaClass, Pageable pageable, Locale locale) { Query query = new Query(); Query queryTotal = new Query(); - if (!user.getSelfOrImpersonated().isAdmin()) - query.addCriteria(getProcessRolesCriteria(user.getSelfOrImpersonated())); - if (criteriaClass.getIdentifier() != null) { this.addValueCriteria(query, queryTotal, Criteria.where("identifier").regex(criteriaClass.getIdentifier(), "i")); } @@ -484,42 +512,28 @@ public Page<PetriNetReference> search(PetriNetSearch criteriaClass, LoggedUser u this.addValueCriteria(query, queryTotal, Criteria.where("title.defaultValue").regex(criteriaClass.getTitle(), "i")); } if (criteriaClass.getInitials() != null) { - this.addValueCriteria(query, queryTotal, Criteria.where("initials").regex(criteriaClass.getInitials(), "i")); + // todo: release/8.0.0 does not work - see PetriNetServiceTest + this.addValueCriteria(query, queryTotal, Criteria.where("properties.initials").regex(criteriaClass.getInitials(), "i")); } if (criteriaClass.getDefaultCaseName() != null) { this.addValueCriteria(query, queryTotal, Criteria.where("defaultCaseName.defaultValue").regex(criteriaClass.getDefaultCaseName(), "i")); } - if (criteriaClass.getGroup() != null) { - if (criteriaClass.getGroup().size() == 1) { - this.addValueCriteria(query, queryTotal, Criteria.where("author.email").is(this.groupService.getGroupOwnerEmail(criteriaClass.getGroup().get(0)))); - } else { - this.addValueCriteria(query, queryTotal, Criteria.where("author.email").in(this.groupService.getGroupsOwnerEmails(criteriaClass.getGroup()))); - } - } if (criteriaClass.getVersion() != null) { this.addValueCriteria(query, queryTotal, Criteria.where("version").is(criteriaClass.getVersion())); } if (criteriaClass.getAuthor() != null) { - if (criteriaClass.getAuthor().getEmail() != null) { - this.addValueCriteria(query, queryTotal, Criteria.where("author.email").is(criteriaClass.getAuthor().getEmail())); - } - if (criteriaClass.getAuthor().getId() != null) { - this.addValueCriteria(query, queryTotal, Criteria.where("author.id").is(criteriaClass.getAuthor().getId())); - } - if (criteriaClass.getAuthor().getFullName() != null) { - this.addValueCriteria(query, queryTotal, Criteria.where("author.fullName").is(criteriaClass.getAuthor().getFullName())); - } + this.addValueCriteria(query, queryTotal, Criteria.where("authorId").is(criteriaClass.getAuthor().getCase().getStringId())); } - if (criteriaClass.getNegativeViewRoles() != null) { - this.addValueCriteria(query, queryTotal, Criteria.where("negativeViewRoles").in(criteriaClass.getNegativeViewRoles())); + if (criteriaClass.getNegativeViewProcessRoles() != null) { + this.addValueCriteria(query, queryTotal, Criteria.where("negativeViewProcessRoles").in(criteriaClass.getNegativeViewProcessRoles())); } if (criteriaClass.getTags() != null) { - criteriaClass.getTags().entrySet().forEach(stringStringEntry -> this.addValueCriteria(query, queryTotal, Criteria.where("tags." + stringStringEntry.getKey()).is(stringStringEntry.getValue()))); + criteriaClass.getTags().forEach((key, value) -> this.addValueCriteria(query, queryTotal, Criteria.where("properties." + key).is(value))); } query.with(pageable); - List<PetriNet> nets = mongoTemplate.find(query, PetriNet.class); - return new PageImpl<>(nets.stream().map(net -> new PetriNetReference(net, locale)).collect(Collectors.toList()), pageable, mongoTemplate.count(queryTotal, PetriNet.class)); + List<Process> nets = mongoTemplate.find(query, Process.class); + return new PageImpl<>(nets.stream().map(net -> new PetriNetReference(net, locale)).collect(Collectors.toList()), pageable, mongoTemplate.count(queryTotal, Process.class)); } private void addValueCriteria(Query query, Query queryTotal, Criteria criteria) { @@ -527,44 +541,75 @@ private void addValueCriteria(Query query, Query queryTotal, Criteria criteria) queryTotal.addCriteria(criteria); } - @Override - @Transactional - public void deletePetriNet(String processId, LoggedUser loggedUser) { - Optional<PetriNet> petriNetOptional = repository.findById(processId); - if (!petriNetOptional.isPresent()) { + /** + * Removes {@link Process} along with its Cases and roles + * + * @param deleteProcessParams parameters for PetriNet removal + * <br> + * <b>Required parameters</b> + * <ul> + * <li>petriNetId</li> + * </ul> + * */ + @Override + public void deleteProcess(DeleteProcessParams deleteProcessParams) { + if (deleteProcessParams.isTransactional() && !TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<>(null) { + @Override + public Object call() { + doDeleteProcess(deleteProcessParams); + return null; + } + }) + .build(); + transaction.begin(); + } else { + doDeleteProcess(deleteProcessParams); + } + } + + private void doDeleteProcess(DeleteProcessParams deleteProcessParams) { + String processId = deleteProcessParams.getProcessId(); + + Optional<Process> petriNetOptional = repository.findById(processId); + if (petriNetOptional.isEmpty()) { throw new IllegalArgumentException("Could not find process with id [" + processId + "]"); } + Process process = petriNetOptional.get(); + List<Process> childProcesses = repository.findAllChildrenByParentId(process.getObjectId()); + for (Process childProcess : childProcesses) { + doDeleteProcess(childProcess); + } + doDeleteProcess(process); + } - PetriNet petriNet = petriNetOptional.get(); - log.info("[{}]: Initiating deletion of Petri net {} version {}", processId, petriNet.getIdentifier(), petriNet.getVersion().toString()); + private void doDeleteProcess(Process process) { + log.info("[{}]: Initiating deletion of Process [{}] version [{}]", process.getStringId(), process.getIdentifier(), + process.getVersion().toString()); - this.userService.removeRoleOfDeletedPetriNet(petriNet); - this.workflowService.deleteInstancesOfPetriNet(petriNet); - this.processRoleService.deleteRolesOfNet(petriNet, loggedUser); + this.workflowService.deleteInstancesOfPetriNet(process); try { - ldapGroupService.deleteProcessRoleByPetrinet(petriNet.getStringId()); + // todo: release/8.0.0 ldap + ldapGroupService.deleteRoleByPetriNet(process.getStringId()); } catch (NullPointerException e) { log.info("LdapGroup and ProcessRole mapping are not activated..."); } catch (Exception ex) { log.error("LdapGroup", ex); } - - log.info("[{}]: User [{}] is deleting Petri net {} version {}", processId, userService.getLoggedOrSystem().getStringId(), petriNet.getIdentifier(), petriNet.getVersion().toString()); - this.repository.deleteById(petriNet.getObjectId()); - this.evictCache(petriNet); - // net functions must be removed from cache after it was deleted from repository - this.functionCacheService.reloadCachedFunctions(petriNet); - historyService.save(new DeletePetriNetEventLog(null, EventPhase.PRE, petriNet.getObjectId())); - } - - private Criteria getProcessRolesCriteria(LoggedUser user) { - return new Criteria().orOperator(user.getProcessRoles().stream() - .map(role -> Criteria.where("permissions." + role).exists(true)).toArray(Criteria[]::new)); + log.info("[{}]: Actor [{}] is deleting Petri net {} version {}", process.getStringId(), + sessionManagerService.getActiveActorId(), process.getIdentifier(), process.getVersion().toString()); + this.repository.deleteById(process.getObjectId()); + this.evictCache(process); + // process functions must be removed from a cache after it was deleted from the repository + this.functionCacheService.reloadCachedFunctions(process); + historyService.save(new DeletePetriNetEventLog(null, EventPhase.PRE, process.getObjectId())); } @Override - public void runActions(List<Action> actions, PetriNet petriNet) { + public void runActions(List<Action> actions, Process petriNet) { log.info("Running actions of net [{}]", petriNet.getStringId()); actions.forEach(action -> { diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/ProcessRoleService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/ProcessRoleService.java deleted file mode 100644 index 0e06a5ddb8a..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/ProcessRoleService.java +++ /dev/null @@ -1,326 +0,0 @@ -package com.netgrif.application.engine.petrinet.service; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.event.events.user.UserRoleChangeEvent; -import com.netgrif.application.engine.importer.model.EventPhaseType; -import com.netgrif.application.engine.importer.model.EventType; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionRunner; -import com.netgrif.application.engine.petrinet.domain.events.Event; -import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; -import com.netgrif.application.engine.security.service.ISecurityContextService; -import lombok.extern.slf4j.Slf4j; -import org.bson.types.ObjectId; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Service; - -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -@Slf4j -@Service -public class ProcessRoleService implements IProcessRoleService { - - private final IUserService userService; - private final ProcessRoleRepository processRoleRepository; - private final PetriNetRepository netRepository; - private final ApplicationEventPublisher publisher; - private final IPetriNetService petriNetService; - private final ISecurityContextService securityContextService; - private final ActionRunner actionsRunner; - - private ProcessRole defaultRole; - private ProcessRole anonymousRole; - - public ProcessRoleService( - ProcessRoleRepository processRoleRepository, - PetriNetRepository netRepository, - ApplicationEventPublisher publisher, - @Lazy IPetriNetService petriNetService, - @Lazy IUserService userService, - ISecurityContextService securityContextService, - ActionRunner actionsRunner - ) { - this.processRoleRepository = processRoleRepository; - this.netRepository = netRepository; - this.publisher = publisher; - this.petriNetService = petriNetService; - this.userService = userService; - this.securityContextService = securityContextService; - this.actionsRunner = actionsRunner; - } - - @Override - public List<ProcessRole> saveAll(Iterable<ProcessRole> entities) { - return processRoleRepository.saveAll(entities); - } - - @Override - public Set<ProcessRole> findByIds(Set<String> ids) { - return StreamSupport.stream(processRoleRepository.findAllById(ids).spliterator(), false).collect(Collectors.toSet()); - } - - @Override - public void assignRolesToUser(String userId, Set<String> requestedRolesIds, LoggedUser loggedUser) { - assignRolesToUser(userId, requestedRolesIds, loggedUser, new HashMap<>()); - } - - @Override - public void assignRolesToUser(String userId, Set<String> requestedRolesIds, LoggedUser loggedUser, Map<String, String> params) { - IUser user = userService.resolveById(userId); - Set<ProcessRole> requestedRoles = this.findByIds(requestedRolesIds); - if (requestedRoles.isEmpty() && !requestedRolesIds.isEmpty()) { - throw new IllegalArgumentException("No process roles found."); - } - if (requestedRoles.size() != requestedRolesIds.size()) { - throw new IllegalArgumentException("Not all process roles were found!"); - } - - Set<ProcessRole> userOldRoles = user.getProcessRoles(); - - Set<ProcessRole> rolesNewToUser = getRolesNewToUser(userOldRoles, requestedRoles); - Set<ProcessRole> rolesRemovedFromUser = getRolesRemovedFromUser(userOldRoles, requestedRoles); - - String idOfPetriNetContainingRole = getPetriNetIdRoleBelongsTo(rolesNewToUser, rolesRemovedFromUser); - - if (idOfPetriNetContainingRole == null) { - return; - } - - PetriNet petriNet = petriNetService.getPetriNet(idOfPetriNetContainingRole); - - Set<String> rolesNewToUserIds = mapUserRolesToIds(rolesNewToUser); - Set<String> rolesRemovedFromUserIds = mapUserRolesToIds(rolesRemovedFromUser); - - Set<ProcessRole> newRoles = this.findByIds(rolesNewToUserIds); - Set<ProcessRole> removedRoles = this.findByIds(rolesRemovedFromUserIds); - - runAllPreActions(newRoles, removedRoles, user, petriNet, params); - user = userService.findById(userId); - requestedRoles = updateRequestedRoles(user, rolesNewToUser, rolesRemovedFromUser); - - replaceUserRolesAndPublishEvent(requestedRolesIds, user, requestedRoles); - runAllPostActions(newRoles, removedRoles, user, petriNet, params); - - securityContextService.saveToken(userId); - if (Objects.equals(userId, loggedUser.getId())) { - loggedUser.getProcessRoles().clear(); - loggedUser.parseProcessRoles(user.getProcessRoles()); - securityContextService.reloadSecurityContext(loggedUser); - } - } - - private Set<ProcessRole> updateRequestedRoles(IUser user, Set<ProcessRole> rolesNewToUser, Set<ProcessRole> rolesRemovedFromUser) { - Set<ProcessRole> userRolesAfterPreActions = user.getProcessRoles(); - userRolesAfterPreActions.addAll(rolesNewToUser); - userRolesAfterPreActions.removeAll(rolesRemovedFromUser); - - return new HashSet<>(userRolesAfterPreActions); - } - - private String getPetriNetIdRoleBelongsTo(Set<ProcessRole> newRoles, Set<ProcessRole> removedRoles) { - if (!newRoles.isEmpty()) { - return getPetriNetIdFromFirstRole(newRoles); - } - - if (!removedRoles.isEmpty()) { - return getPetriNetIdFromFirstRole(removedRoles); - } - - return null; - } - - private String getPetriNetIdFromFirstRole(Set<ProcessRole> newRoles) { - return newRoles.iterator().next().getNetId(); - } - - private void replaceUserRolesAndPublishEvent(Set<String> requestedRolesIds, IUser user, Set<ProcessRole> requestedRoles) { - removeOldAndAssignNewRolesToUser(user, requestedRoles); - publisher.publishEvent(new UserRoleChangeEvent(user, this.findByIds(requestedRolesIds))); - } - - private Set<ProcessRole> getRolesNewToUser(Set<ProcessRole> userOldRoles, Set<ProcessRole> newRequestedRoles) { - Set<ProcessRole> rolesNewToUser = new HashSet<>(newRequestedRoles); - rolesNewToUser.removeAll(userOldRoles); - - return rolesNewToUser; - } - - private Set<ProcessRole> getRolesRemovedFromUser(Set<ProcessRole> userOldRoles, Set<ProcessRole> newRequestedRoles) { - Set<ProcessRole> rolesRemovedFromUser = new HashSet<>(userOldRoles); - rolesRemovedFromUser.removeAll(newRequestedRoles); - - return rolesRemovedFromUser; - } - - private Set<String> mapUserRolesToIds(Collection<ProcessRole> processRoles) { - return processRoles.stream() - .map(ProcessRole::getStringId) - .collect(Collectors.toSet()); - } - - private void runAllPreActions(Set<ProcessRole> newRoles, Set<ProcessRole> removedRoles, IUser user, PetriNet petriNet, Map<String, String> params) { - runAllSuitableActionsOnRoles(newRoles, EventType.ASSIGN, EventPhaseType.PRE, user, petriNet, params); - runAllSuitableActionsOnRoles(removedRoles, EventType.CANCEL, EventPhaseType.PRE, user, petriNet, params); - } - - private void runAllPostActions(Set<ProcessRole> newRoles, Set<ProcessRole> removedRoles, IUser user, PetriNet petriNet, Map<String, String> params) { - runAllSuitableActionsOnRoles(newRoles, EventType.ASSIGN, EventPhaseType.POST, user, petriNet, params); - runAllSuitableActionsOnRoles(removedRoles, EventType.CANCEL, EventPhaseType.POST, user, petriNet, params); - } - - private void runAllSuitableActionsOnRoles(Set<ProcessRole> roles, EventType requiredEventType, EventPhaseType requiredPhase, IUser user, PetriNet petriNet, Map<String, String> params) { - roles.forEach(role -> { - runAllSuitableActionsOnOneRole(role.getEvents(), requiredEventType, requiredPhase, params); - }); - } - - // TODO: release/8.0.0 fix - private void runAllSuitableActionsOnOneRole(Map<EventType, Event> eventMap, EventType requiredEventType, EventPhaseType requiredPhase, Map<String, String> params) { - if (eventMap == null) { - return; - } - eventMap.forEach((eventType, event) -> { - if (eventType != requiredEventType) { - return; - } - - runActionsBasedOnPhase(event, requiredPhase, params); - }); - } - - private void runActionsBasedOnPhase(Event event, EventPhaseType requiredPhase, Map<String, String> params) { - switch (requiredPhase) { - case PRE: - runActions(event.getPreActions(), params); - break; - case POST: - runActions(event.getPostActions(), params); - break; - } - } - - private void runActions(List<Action> actions, Map<String, String> params) { - actions.forEach(action -> actionsRunner.run(action, null, params)); - } - - private void removeOldAndAssignNewRolesToUser(IUser user, Set<ProcessRole> requestedRoles) { - user.getProcessRoles().clear(); - user.getProcessRoles().addAll(requestedRoles); - - userService.save(user); - } - - @Override - public List<ProcessRole> findAll() { - return processRoleRepository.findAll(); - } - - @Override - public List<ProcessRole> findAll(String netId) { - Optional<PetriNet> netOptional = netRepository.findById(netId); - if (netOptional.isEmpty()) { - throw new IllegalArgumentException("Could not find model with id [" + netId + "]"); - } - return findAll(netOptional.get()); - } - - private List<ProcessRole> findAll(PetriNet net) { - return new LinkedList<>(net.getRoles().values()); - } - - @Override - public ProcessRole defaultRole() { - // TODO: release/8.0.0 duplicate code - if (defaultRole == null) { - Set<ProcessRole> roles = processRoleRepository.findAllByName_DefaultValue(ProcessRole.DEFAULT_ROLE); - if (roles.isEmpty()) { - throw new IllegalStateException("No default process role has been found!"); - } - if (roles.size() > 1) { - throw new IllegalStateException("More than 1 default process role exists!"); - } - defaultRole = roles.stream().findFirst().orElse(null); - } - return defaultRole; - } - - @Override - public ProcessRole anonymousRole() { - if (anonymousRole == null) { - Set<ProcessRole> roles = processRoleRepository.findAllByImportId(ProcessRole.ANONYMOUS_ROLE); - if (roles.isEmpty()) { - throw new IllegalStateException("No anonymous process role has been found!"); - } - if (roles.size() > 1) { - throw new IllegalStateException("More than 1 anonymous process role exists!"); - } - anonymousRole = roles.stream().findFirst().orElse(null); - } - return anonymousRole; - } - - /** - * @param importId id from a process of a role - * @return a process role object - * @deprecated use {@link ProcessRoleService#findAllByImportId(String)} instead - */ - @Deprecated(forRemoval = true, since = "6.2.0") - @Override - public ProcessRole findByImportId(String importId) { - return processRoleRepository.findAllByImportId(importId).stream().findFirst().orElse(null); - } - - @Override - public Set<ProcessRole> findAllByImportId(String importId) { - return processRoleRepository.findAllByImportId(importId); - } - - @Override - public Set<ProcessRole> findAllByDefaultName(String name) { - return processRoleRepository.findAllByName_DefaultValue(name); - } - - @Override - public ProcessRole findById(String id) { - return processRoleRepository.findById(id).orElse(null); - } - - @Override - public void deleteRolesOfNet(PetriNet net, LoggedUser loggedUser) { - log.info("[{}]: Initiating deletion of all roles of Petri net {} version {}", net.getStringId(), net.getIdentifier(), net.getVersion().toString()); - List<ObjectId> deletedRoleIds = this.findAll(net).stream().map(ProcessRole::getId).collect(Collectors.toList()); - Set<String> deletedRoleStringIds = deletedRoleIds.stream().map(ObjectId::toString).collect(Collectors.toSet()); - - List<IUser> usersWithRemovedRoles = this.userService.findAllByProcessRoles(deletedRoleStringIds); - for (IUser user : usersWithRemovedRoles) { - log.info("[{}]: Removing deleted roles of Petri net {} version {} from user {} with id {}", net.getStringId(), net.getIdentifier(), net.getVersion().toString(), user.getFullName(), user.getStringId()); - if (user.getProcessRoles().isEmpty()) { - continue; - } - - Set<String> newRoles = user.getProcessRoles().stream() - .filter(role -> !deletedRoleStringIds.contains(role.getStringId())) - .map(ProcessRole::getStringId) - .collect(Collectors.toSet()); - this.assignRolesToUser(user.getStringId(), newRoles, loggedUser); - } - - log.info("[{}]: Deleting all roles of Petri net {} version {}", net.getStringId(), net.getIdentifier(), net.getVersion().toString()); - this.processRoleRepository.deleteAllByIdIn(deletedRoleIds); - } - - public void clearCache() { - this.defaultRole = null; - this.anonymousRole = null; - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/UriService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/UriService.java index 2a6a3cff879..e57f9982e6f 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/UriService.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/service/UriService.java @@ -3,7 +3,7 @@ import com.netgrif.application.engine.configuration.properties.UriProperties; import com.netgrif.application.engine.petrinet.domain.UriContentType; import com.netgrif.application.engine.petrinet.domain.UriNode; -import com.netgrif.application.engine.petrinet.domain.repository.UriNodeRepository; +import com.netgrif.application.engine.petrinet.domain.repositories.UriNodeRepository; import com.netgrif.application.engine.petrinet.service.interfaces.IUriService; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetAuthorizationService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetAuthorizationService.java deleted file mode 100644 index 2adb86c5749..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetAuthorizationService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.netgrif.application.engine.petrinet.service.interfaces; - -import com.netgrif.application.engine.auth.domain.LoggedUser; - -public interface IPetriNetAuthorizationService { - - boolean canCallProcessDelete(LoggedUser loggedUser, String processId); - -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java index 9f03b747219..a0059471804 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java @@ -1,112 +1,97 @@ package com.netgrif.application.engine.petrinet.service.interfaces; -import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.petrinet.domain.Transition; -import com.netgrif.application.engine.petrinet.domain.VersionType; import com.netgrif.application.engine.petrinet.domain.dataset.Field; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; +import com.netgrif.application.engine.petrinet.domain.params.DeleteProcessParams; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; import com.netgrif.application.engine.petrinet.domain.version.Version; import com.netgrif.application.engine.petrinet.web.responsebodies.DataFieldReference; import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetImportReference; import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference; import com.netgrif.application.engine.petrinet.web.responsebodies.TransitionReference; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; import org.bson.types.ObjectId; import org.springframework.core.io.FileSystemResource; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import java.io.IOException; -import java.io.InputStream; import java.util.*; public interface IPetriNetService { //TODO release/8.0.0 resolve - static PetriNetReference transformToReference(PetriNet net, Locale locale) { + static PetriNetReference transformToReference(Process net, Locale locale) { //return new PetriNetReference(net.getStringId(), net.getIdentifier(), net.getVersion(), net.getTitle().getTranslation(locale), net.getInitials(), net.getTranslatedDefaultCaseName(locale)); return new PetriNetReference(net, locale); } - static TransitionReference transformToReference(PetriNet net, Transition transition, Locale locale) { + static TransitionReference transformToReference(Process net, Transition transition, Locale locale) { List<com.netgrif.application.engine.workflow.web.responsebodies.DataFieldReference> list = new ArrayList<>(); transition.getImmediateData().forEach(fieldId -> list.add(new com.netgrif.application.engine.workflow.web.responsebodies.DataFieldReference(net.getDataSet().get(fieldId), locale))); return new TransitionReference(transition.getStringId(), transition.getTitle().getTranslation(locale), net.getStringId(), list); } - static DataFieldReference transformToReference(PetriNet net, Transition transition, Field field, Locale locale) { - return new DataFieldReference(field.getStringId(), field.getName().getTranslation(locale), net.getStringId(), transition.getStringId()); + static DataFieldReference transformToReference(Process net, Transition transition, Field field, Locale locale) { + return new DataFieldReference(field.getStringId(), field.getTitle().getTranslation(locale), net.getStringId(), transition.getStringId()); } - PetriNet clone(ObjectId petriNetId); + Process clone(ObjectId petriNetId); - @Deprecated - ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, String releaseType, LoggedUser user) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException; + ImportPetriNetEventOutcome importProcess(ImportProcessParams importProcessParams) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException; - @Deprecated - ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, String releaseType, LoggedUser user, String uriNodeId) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException; + Optional<Process> save(Process petriNet); - ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser user) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException; + Process getPetriNet(String id); - ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser user, Map<String, String> params) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException; + Process getPetriNet(String identifier, Version version); - ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser user, String uriNodeId) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException; + List<Process> getByIdentifier(String identifier); - ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser user, String uriNodeId, Map<String, String> params) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException; + List<Process> findAllByUriNodeId(String uriNodeId); - Optional<PetriNet> save(PetriNet petriNet); + List<Process> findAllById(List<String> ids); - PetriNet getPetriNet(String id); + Process getNewestVersionByIdentifier(String identifier); - PetriNet getPetriNet(String identifier, Version version); - - List<PetriNet> getByIdentifier(String identifier); - - List<PetriNet> findAllByUriNodeId(String uriNodeId); - - List<PetriNet> findAllById(List<String> ids); - - PetriNet getNewestVersionByIdentifier(String identifier); - - List<PetriNet> getAll(); + List<Process> getAll(); FileSystemResource getFile(String netId, String title); - List<PetriNetReference> getReferences(LoggedUser user, Locale locale); - - List<PetriNetReference> getReferencesByIdentifier(String identifier, LoggedUser user, Locale locale); + List<PetriNetReference> getReferences(Locale locale); - List<PetriNetReference> getReferencesByVersion(Version version, LoggedUser user, Locale locale); + List<PetriNetReference> getReferencesByIdentifier(String identifier, Locale locale); - List<PetriNetReference> getReferencesByUsersProcessRoles(LoggedUser user, Locale locale); + List<PetriNetReference> getReferencesByVersion(Version version, Locale locale); - PetriNetReference getReference(String identifier, Version version, LoggedUser user, Locale locale); + PetriNetReference getReference(String identifier, Version version, Locale locale); - List<TransitionReference> getTransitionReferences(List<String> netsIds, LoggedUser user, Locale locale); + List<TransitionReference> getTransitionReferences(List<String> netsIds, Locale locale); List<DataFieldReference> getDataFieldReferences(List<TransitionReference> transitions, Locale locale); - Page<PetriNetReference> search(PetriNetSearch criteria, LoggedUser user, Pageable pageable, Locale locale); + Page<PetriNetReference> search(PetriNetSearch criteria, Pageable pageable, Locale locale); - Optional<PetriNet> findByImportId(String id); + Optional<Process> findByImportId(String id); void evictAllCaches(); - void evictCache(PetriNet net); + void evictCache(Process net); - PetriNet get(ObjectId petriNetId); + Process get(ObjectId petriNetId); - List<PetriNet> get(Collection<ObjectId> petriNetId); + List<Process> get(Collection<ObjectId> petriNetId); - List<PetriNet> get(List<String> petriNetIds); + List<Process> get(List<String> petriNetIds); - void deletePetriNet(String id, LoggedUser loggedUser); + void deleteProcess(DeleteProcessParams deleteProcessParams); - void runActions(List<Action> actions, PetriNet petriNet); + void runActions(List<Action> actions, Process petriNet); List<String> getExistingPetriNetIdentifiersFromIdentifiersList(List<String> identifiers); diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IProcessRoleService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IProcessRoleService.java deleted file mode 100644 index 769661adf02..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IProcessRoleService.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.netgrif.application.engine.petrinet.service.interfaces; - -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -public interface IProcessRoleService { - - List<ProcessRole> saveAll(Iterable<ProcessRole> entities); - - Set<ProcessRole> findAllByImportId(String importId); - - Set<ProcessRole> findAllByDefaultName(String name); - - ProcessRole findById(String id); - - Set<ProcessRole> findByIds(Set<String> ids); - - ProcessRole findByImportId(String importId); - - void assignRolesToUser(String userId, Set<String> roleIds, LoggedUser user); - - void assignRolesToUser(String userId, Set<String> roleIds, LoggedUser user, Map<String, String> params); - - List<ProcessRole> findAll(); - - List<ProcessRole> findAll(String netId); - - ProcessRole defaultRole(); - - ProcessRole anonymousRole(); - - void deleteRolesOfNet(PetriNet net, LoggedUser loggedUser); -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index 32435667252..66913d44ab7 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -1,21 +1,20 @@ package com.netgrif.application.engine.petrinet.web; import com.netgrif.application.engine.AsyncRunner; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.importer.service.Importer; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; -import com.netgrif.application.engine.petrinet.domain.PetriNet; import com.netgrif.application.engine.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.petrinet.domain.VersionType; +import com.netgrif.application.engine.petrinet.domain.params.DeleteProcessParams; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; import com.netgrif.application.engine.petrinet.domain.version.StringToVersionConverter; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; import com.netgrif.application.engine.petrinet.web.responsebodies.*; -import com.netgrif.application.engine.workflow.domain.FileStorageConfiguration; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessage; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessageResource; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response.EventOutcomeWithMessage; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response.EventOutcomeWithMessageResource; import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -62,22 +61,16 @@ @Tag(name = "PetriNet") public class PetriNetController { - @Autowired - private FileStorageConfiguration fileStorageConfiguration; - @Autowired private IPetriNetService service; - @Autowired - private IProcessRoleService roleService; - @Autowired private StringToVersionConverter converter; @Autowired private AsyncRunner asyncRunner; - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") @Operation(summary = "Import new process", description = "Caller must have the ADMIN role. Imports an entirely new process or a new version of an existing process.", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -94,7 +87,13 @@ public EntityModel<EventOutcomeWithMessage> importPetriNet( Authentication auth, Locale locale) throws MissingPetriNetMetaDataException, MissingIconKeyException { try { VersionType release = releaseType == null ? VersionType.MAJOR : VersionType.valueOf(releaseType.trim().toUpperCase()); - ImportPetriNetEventOutcome importPetriNetOutcome = service.importPetriNet(multipartFile.getInputStream(), release, (LoggedUser) auth.getPrincipal(), uriNodeId); + ImportProcessParams importProcessParams = ImportProcessParams.with() + .xmlFile(multipartFile.getInputStream()) + .releaseType(release) + .authorId(((LoggedIdentity) auth.getPrincipal()).getActiveActorId()) + .uriNodeId(uriNodeId) + .build(); + ImportPetriNetEventOutcome importPetriNetOutcome = service.importProcess(importProcessParams); return EventOutcomeWithMessageResource.successMessage("Petri net " + multipartFile.getOriginalFilename() + " imported successfully", importPetriNetOutcome); } catch (IOException e) { log.error("Importing Petri net failed: ", e); @@ -104,16 +103,15 @@ public EntityModel<EventOutcomeWithMessage> importPetriNet( @Operation(summary = "Get all processes", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(produces = MediaTypes.HAL_JSON_VALUE) - public PetriNetReferenceResources getAll(@RequestParam(value = "indentifier", required = false) String identifier, @RequestParam(value = "version", required = false) String version, Authentication auth, Locale locale) { - LoggedUser user = (LoggedUser) auth.getPrincipal(); + public PetriNetReferenceResources getAll(@RequestParam(value = "identifier", required = false) String identifier, @RequestParam(value = "version", required = false) String version, Authentication auth, Locale locale) { if (identifier != null && version == null) { - return new PetriNetReferenceResources(service.getReferencesByIdentifier(identifier, user, locale)); + return new PetriNetReferenceResources(service.getReferencesByIdentifier(identifier, locale)); } else if (identifier == null && version != null) { - return new PetriNetReferenceResources(service.getReferencesByVersion(converter.convert(version), user, locale)); + return new PetriNetReferenceResources(service.getReferencesByVersion(converter.convert(version), locale)); } else if (identifier != null && version != null) { - return new PetriNetReferenceResources(Collections.singletonList(service.getReference(identifier, converter.convert(version), user, locale))); + return new PetriNetReferenceResources(Collections.singletonList(service.getReference(identifier, converter.convert(version), locale))); } else { - return new PetriNetReferenceResources(service.getReferences(user, locale)); + return new PetriNetReferenceResources(service.getReferences(locale)); } } @@ -127,14 +125,14 @@ public PetriNetReferenceResource getOne(@PathVariable("id") String id, Authentic @GetMapping(value = "/{identifier}/{version}", produces = MediaTypes.HAL_JSON_VALUE) public PetriNetReferenceResource getOne(@PathVariable("identifier") String identifier, @PathVariable("version") String version, Authentication auth, Locale locale) { String resolvedIdentifier = Base64.isBase64(identifier) ? new String(Base64.decodeBase64(identifier)) : identifier; - return new PetriNetReferenceResource(service.getReference(resolvedIdentifier, converter.convert(version), (LoggedUser) auth.getPrincipal(), locale)); + return new PetriNetReferenceResource(service.getReference(resolvedIdentifier, converter.convert(version), locale)); } @Operation(summary = "Get transitions of processes", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/transitions", produces = MediaTypes.HAL_JSON_VALUE) public TransitionReferencesResource getTransitionReferences(@RequestParam List<String> ids, Authentication auth, Locale locale) { ids.forEach(id -> id = decodeUrl(id)); - return new TransitionReferencesResource(service.getTransitionReferences(ids, (LoggedUser) auth.getPrincipal(), locale)); + return new TransitionReferencesResource(service.getTransitionReferences(ids, locale)); } @Operation(summary = "Get data fields of transitions", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -143,21 +141,7 @@ public DataFieldReferencesResource getDataFieldReferences(@RequestBody List<Tran return new DataFieldReferencesResource(service.getDataFieldReferences(referenceBody, locale)); } - @Operation(summary = "Get roles of process", security = {@SecurityRequirement(name = "BasicAuth")}) - @GetMapping(value = "/{netId}/roles", produces = MediaTypes.HAL_JSON_VALUE) - public ProcessRolesResource getRoles(@PathVariable("netId") String netId, Locale locale) { - netId = decodeUrl(netId); - return new ProcessRolesResource(roleService.findAll(netId), service.getPetriNet(decodeUrl(netId)).getPermissions(), netId, locale); - } - - @Operation(summary = "Get transactions of process", security = {@SecurityRequirement(name = "BasicAuth")}) - @GetMapping(value = "/{netId}/transactions", produces = MediaTypes.HAL_JSON_VALUE) - public TransactionsResource getTransactions(@PathVariable("netId") String netId, Locale locale) { - PetriNet net = service.getPetriNet(decodeUrl(netId)); - return new TransactionsResource(net.getTransactions().values(), netId, locale); - } - - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") @Operation(summary = "Download process model", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/{netId}/file", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) public FileSystemResource getNetFile(@PathVariable("netId") String netId, @RequestParam(value = "title", required = false) String title, Authentication auth, HttpServletResponse response) { @@ -173,8 +157,7 @@ public FileSystemResource getNetFile(@PathVariable("netId") String netId, @Reque @PostMapping(value = "/search", produces = MediaTypes.HAL_JSON_VALUE) public @ResponseBody PagedModel<PetriNetReferenceResource> searchPetriNets(@RequestBody PetriNetSearch criteria, Authentication auth, Pageable pageable, PagedResourcesAssembler<PetriNetReference> assembler, Locale locale) { - LoggedUser user = (LoggedUser) auth.getPrincipal(); - Page<PetriNetReference> nets = service.search(criteria, user, pageable, locale); + Page<PetriNetReference> nets = service.search(criteria, pageable, locale); Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(PetriNetController.class) .searchPetriNets(criteria, auth, pageable, assembler, locale)).withRel("search"); PagedModel<PetriNetReferenceResource> resources = assembler.toModel(nets, new PetriNetReferenceResourceAssembler(), selfLink); @@ -182,7 +165,7 @@ PagedModel<PetriNetReferenceResource> searchPetriNets(@RequestBody PetriNetSearc return resources; } - @PreAuthorize("@petriNetAuthorizationService.canCallProcessDelete(#auth.getPrincipal(), #processId)") + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") @Operation(summary = "Delete process", description = "Caller must have the ADMIN role. Removes the specified process, along with it's cases, tasks and process roles.", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -197,8 +180,7 @@ public MessageResource deletePetriNet(@PathVariable("id") String processId, Auth log.error("Deleting Petri net [{}] failed: could not decode process ID from URL", processId); return MessageResource.errorMessage("Deleting Petri net " + processId + " failed!"); } - LoggedUser user = (LoggedUser) auth.getPrincipal(); - asyncRunner.execute(() -> this.service.deletePetriNet(decodedProcessId, user)); + asyncRunner.execute(() -> this.service.deleteProcess(new DeleteProcessParams(decodedProcessId))); return MessageResource.successMessage("Petri net " + decodedProcessId + " is being deleted"); } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PublicPetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PublicPetriNetController.java index 101c6d0df1f..6d322e8ddd2 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PublicPetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PublicPetriNetController.java @@ -1,14 +1,12 @@ package com.netgrif.application.engine.petrinet.web; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.petrinet.domain.PetriNet; import com.netgrif.application.engine.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.petrinet.domain.version.StringToVersionConverter; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; import com.netgrif.application.engine.petrinet.web.responsebodies.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -29,6 +27,7 @@ @Slf4j @RestController +@RequiredArgsConstructor @ConditionalOnProperty( value = "nae.public.petrinet.web.enabled", havingValue = "true", @@ -39,20 +38,8 @@ public class PublicPetriNetController { private final IPetriNetService petriNetService; - - private final IProcessRoleService roleService; - - private final IUserService userService; - private final StringToVersionConverter converter; - public PublicPetriNetController(IPetriNetService petriNetService, IUserService userService, StringToVersionConverter converter, IProcessRoleService roleService) { - this.petriNetService = petriNetService; - this.converter = converter; - this.userService = userService; - this.roleService = roleService; - } - @GetMapping(value = "/{id}", produces = MediaTypes.HAL_JSON_VALUE) @Operation(summary = "Get process by id") public PetriNetReferenceResource getOne(@PathVariable("id") String id, Locale locale) { @@ -64,13 +51,13 @@ public PetriNetReferenceResource getOne(@PathVariable("id") String id, Locale lo @ResponseBody public PetriNetReferenceResource getOne(@PathVariable("identifier") String identifier, @PathVariable("version") String version, Locale locale) { String resolvedIdentifier = Base64.isBase64(identifier) ? new String(Base64.decodeBase64(identifier)) : identifier; - return new PetriNetReferenceResource(this.petriNetService.getReference(resolvedIdentifier, this.converter.convert(version), userService.getAnonymousLogged(), locale)); + return new PetriNetReferenceResource(this.petriNetService.getReference(resolvedIdentifier, this.converter.convert(version), locale)); } @Operation(summary = "Search processes") @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public PagedModel<PetriNetReferenceResource> searchPetriNets(@RequestBody PetriNetSearch criteria, Pageable pageable, PagedResourcesAssembler<PetriNetReference> assembler, Locale locale) { - Page<PetriNetReference> nets = petriNetService.search(criteria, userService.getAnonymousLogged(), pageable, locale); + Page<PetriNetReference> nets = petriNetService.search(criteria, pageable, locale); Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(PublicPetriNetController.class) .searchPetriNets(criteria, pageable, assembler, locale)).withRel("search"); PagedModel<PetriNetReferenceResource> resources = assembler.toModel(nets, new PetriNetReferenceResourceAssembler(), selfLink); @@ -78,20 +65,6 @@ public PagedModel<PetriNetReferenceResource> searchPetriNets(@RequestBody PetriN return resources; } - @Operation(summary = "Get roles of process") - @GetMapping(value = "/{netId}/roles", produces = MediaTypes.HAL_JSON_VALUE) - public ProcessRolesResource getRoles(@PathVariable("netId") String netId, Locale locale) { - netId = decodeUrl(netId); - return new ProcessRolesResource(roleService.findAll(netId), petriNetService.getPetriNet(netId).getPermissions(), netId, locale); - } - - @Operation(summary = "Get transactions of process") - @GetMapping(value = "/{netId}/transactions", produces = MediaTypes.HAL_JSON_VALUE) - public TransactionsResource getTransactions(@PathVariable("netId") String netId, Locale locale) { - PetriNet net = petriNetService.getPetriNet(decodeUrl(netId)); - return new TransactionsResource(net.getTransactions().values(), netId, locale); - } - @Operation(summary = "Get data fields of transitions") @PostMapping(value = "/data", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public DataFieldReferencesResource getDataFieldReferences(@RequestBody List<TransitionReference> referenceBody, Locale locale) { @@ -102,6 +75,6 @@ public DataFieldReferencesResource getDataFieldReferences(@RequestBody List<Tran @GetMapping(value = "/transitions", produces = MediaTypes.HAL_JSON_VALUE) public TransitionReferencesResource getTransitionReferences(@RequestParam List<String> ids, Locale locale) { ids.forEach(PetriNetController::decodeUrl); - return new TransitionReferencesResource(petriNetService.getTransitionReferences(ids, userService.getAnonymousLogged(), locale)); + return new TransitionReferencesResource(petriNetService.getTransitionReferences(ids, locale)); } } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ArcImportReference.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ArcImportReference.java index b4c34fec629..5dddc27fe44 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ArcImportReference.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ArcImportReference.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.petrinet.web.responsebodies; -import com.netgrif.application.engine.petrinet.domain.PetriNetObject; +import com.netgrif.application.engine.petrinet.domain.ProcessObject; import com.netgrif.application.engine.petrinet.domain.Position; import com.netgrif.application.engine.petrinet.domain.arcs.Arc; import com.netgrif.application.engine.petrinet.domain.arcs.InhibitorArc; @@ -11,7 +11,7 @@ import java.util.List; @Data -public class ArcImportReference extends PetriNetObject { +public class ArcImportReference extends ProcessObject { protected String sourceId; @@ -28,7 +28,8 @@ public ArcImportReference(Arc arc) { this.setImportId(arc.getImportId()); this.sourceId = arc.getSourceId(); this.destinationId = arc.getDestinationId(); - this.multiplicity = arc.getMultiplicity(); + // TODO: release/8.0.0 +// this.multiplicity = arc.getMultiplicity(); this.breakpoints = arc.getBreakpoints(); this.type = type(arc); } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReference.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReference.java index ee25b13947d..064962e8e71 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReference.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReference.java @@ -1,8 +1,10 @@ package com.netgrif.application.engine.petrinet.web.responsebodies; -import com.netgrif.application.engine.auth.domain.Author; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.authorization.domain.permissions.AccessPermissions; +import com.netgrif.application.engine.authorization.domain.permissions.CasePermission; +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.utils.UniqueKeyMapWrapper; import com.netgrif.application.engine.workflow.web.responsebodies.DataFieldReference; import lombok.Data; @@ -16,41 +18,33 @@ public class PetriNetReference extends Reference { private String identifier; private String version; - private String initials; private String defaultCaseName; private String icon; private LocalDateTime createdDate; - private Author author; + private String authorId; private List<DataFieldReference> immediateData; + private AccessPermissions<CasePermission> processRolePermissions; + private UniqueKeyMapWrapper<String> properties; public PetriNetReference() { super(); } - public PetriNetReference(String stringId, String identifier, String version, String title, String initials, String defaultCaseName) { + public PetriNetReference(String stringId, String identifier, String version, String title, String authorId, String defaultCaseName) { super(stringId, title); this.identifier = identifier; this.version = version; - this.initials = initials; this.defaultCaseName = defaultCaseName; + this.authorId = authorId; } - public PetriNetReference(String stringId, String title, String identifier, String version, String initials, String icon, LocalDateTime createdDate, Author author) { - super(stringId, title); - this.identifier = identifier; - this.version = version; - this.initials = initials; - this.icon = icon; - this.createdDate = createdDate; - this.author = author; - } - - public PetriNetReference(PetriNet net, Locale locale) { - this(net.getStringId(), net.getIdentifier(), net.getVersion().toString(), net.getTitle().getTranslation(locale), net.getInitials(), net.getTranslatedDefaultCaseName(locale)); + public PetriNetReference(Process net, Locale locale) { + this(net.getStringId(), net.getIdentifier(), net.getVersion().toString(), net.getTitle().getTranslation(locale), net.getAuthorId(), net.getTranslatedDefaultCaseName(locale)); this.icon = net.getIcon(); this.createdDate = net.getCreationDate(); - this.author = net.getAuthor(); this.immediateData = net.getImmediateFields().stream().map(field -> new DataFieldReference(field, locale)).collect(Collectors.toList()); + this.processRolePermissions = net.getProcessRolePermissions(); + this.properties = net.getProperties(); } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResource.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResource.java index 950fa53fec4..bfdac15bb6f 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResource.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResource.java @@ -20,14 +20,6 @@ private void buildLinks() { .methodOn(PetriNetController.class).getOne(getContent().getIdentifier(), getContent().getVersion(), null, null)) .withRel("identifier")); - add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder - .methodOn(PetriNetController.class).getRoles(getContent().getStringId(), null)) - .withRel("roles")); - - add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder - .methodOn(PetriNetController.class).getTransactions(getContent().getStringId(), null)) - .withRel("transaction")); - add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder .methodOn(PetriNetController.class).getNetFile(getContent().getStringId(), getContent().getTitle(), null, null)) .withRel("file")); diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceWithMessage.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceWithMessage.java index a6fcbfc93a2..f7eb5e5f7e1 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceWithMessage.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceWithMessage.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.petrinet.web.responsebodies; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.workflow.web.responsebodies.ResponseMessage; import lombok.Data; @@ -16,7 +16,7 @@ public PetriNetReferenceWithMessage(String msg) { setError(msg); } - public PetriNetReferenceWithMessage(String msg, PetriNet net, Locale locale) { + public PetriNetReferenceWithMessage(String msg, Process net, Locale locale) { super(); setSuccess(msg); setNet(new PetriNetReference(net, locale)); diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceWithMessageResource.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceWithMessageResource.java index f3ffd988a63..520f90dff82 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceWithMessageResource.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceWithMessageResource.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.petrinet.web.responsebodies; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import org.springframework.hateoas.CollectionModel; import java.util.Collections; @@ -12,7 +12,7 @@ public PetriNetReferenceWithMessageResource(PetriNetReferenceWithMessage content super(Collections.singleton(content)); } - public static PetriNetReferenceWithMessageResource successMessage(String msg, PetriNet net, Locale locale) { + public static PetriNetReferenceWithMessageResource successMessage(String msg, Process net, Locale locale) { return new PetriNetReferenceWithMessageResource(new PetriNetReferenceWithMessage(msg, net, locale)); } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PlaceImportReference.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PlaceImportReference.java index d61dce84582..13f827e0d15 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PlaceImportReference.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PlaceImportReference.java @@ -8,15 +8,12 @@ public class PlaceImportReference extends Node { private Integer tokens; - private Boolean isStatic; public PlaceImportReference(Place place) { - this.setPosition(place.getPosition()); this.setTitle(place.getTitle()); this.setObjectId(place.getObjectId()); this.setImportId(place.getImportId()); this.tokens = place.getTokens(); - this.isStatic = place.getIsStatic(); } } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessPermissions.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessPermissions.java deleted file mode 100644 index 3a618e80d94..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessPermissions.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.netgrif.application.engine.petrinet.web.responsebodies; - -import lombok.Data; - -import java.util.HashMap; -import java.util.Map; - -@Data -public class ProcessPermissions { - - private Map<String, Map<String, Boolean>> permissions; - - public ProcessPermissions(Map<String, Map<String, Boolean>> permissions) { - this(); - this.permissions.putAll(permissions); - } - - public ProcessPermissions() { - this.permissions = new HashMap<>(); - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessRole.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessRole.java deleted file mode 100644 index b7cafaaae72..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessRole.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.netgrif.application.engine.petrinet.web.responsebodies; - -import lombok.Data; - -@Data -public class ProcessRole { - - private String stringId; - - private String name; - - private String description; - - public ProcessRole(String id, String name, String description) { - this.stringId = id; - this.name = name; - this.description = description; - } - - public ProcessRole() { - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessRolesAndPermissions.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessRolesAndPermissions.java deleted file mode 100644 index bd3262d2ac6..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessRolesAndPermissions.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.netgrif.application.engine.petrinet.web.responsebodies; - -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission; -import lombok.Data; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Data -public class ProcessRolesAndPermissions { - - private List<ProcessRole> processRoles; - - private Map<String, Map<ProcessRolePermission, Boolean>> permissions; - - public ProcessRolesAndPermissions(List<ProcessRole> processRoles, Map<String, Map<ProcessRolePermission, Boolean>> permissions) { - this(); - this.processRoles = processRoles; - this.permissions.putAll(permissions); - } - - public ProcessRolesAndPermissions() { - this.processRoles = new ArrayList<>(); - this.permissions = new HashMap<>(); - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessRolesResource.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessRolesResource.java deleted file mode 100644 index 35b18478729..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessRolesResource.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.netgrif.application.engine.petrinet.web.responsebodies; - - -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission; -import com.netgrif.application.engine.petrinet.web.PetriNetController; -import org.springframework.hateoas.EntityModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Locale; -import java.util.Map; -import java.util.stream.Collectors; - -public class ProcessRolesResource extends EntityModel<ProcessRolesAndPermissions> { - - public ProcessRolesResource(ProcessRolesAndPermissions content, String netId) { - super(content, new ArrayList<>()); - buildLinks(netId); - } - - public ProcessRolesResource(Collection<com.netgrif.application.engine.petrinet.domain.roles.ProcessRole> content, Map<String, Map<ProcessRolePermission, Boolean>> permissions, String netId, Locale locale) { - this(new ProcessRolesAndPermissions(content.stream().map(role -> new ProcessRole( - role.getStringId(), role.getName().getTranslation(locale), role.getDescription() - )).collect(Collectors.toList()), permissions), netId); - } - - private void buildLinks(String netId) { - add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(PetriNetController.class) - .getRoles(netId, null)).withSelfRel()); - } -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessRolesUsersListResponse.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessRolesUsersListResponse.java deleted file mode 100644 index 598f0072f81..00000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/ProcessRolesUsersListResponse.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.netgrif.application.engine.petrinet.web.responsebodies; - -import com.netgrif.application.engine.auth.domain.IUser; - -import java.util.LinkedList; -import java.util.List; - -public class ProcessRolesUsersListResponse { - List<IUser> users; - - public ProcessRolesUsersListResponse() { - users = new LinkedList<>(); - } - - public List<IUser> getUsers() { - return users; - } - - public void setUsers(List<IUser> users) { - this.users = users; - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/TransactionsResource.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/TransactionsResource.java index 0500c310cfc..74e7b7b2b73 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/TransactionsResource.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/TransactionsResource.java @@ -21,7 +21,8 @@ public TransactionsResource(Collection<Transaction> content, String netId, Local } private void buildLinks(String netId) { - add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(PetriNetController.class) - .getTransactions(netId, null)).withSelfRel()); +// TODO: release/8.0.0 +// add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(PetriNetController.class) +// .getTransactions(netId, null)).withSelfRel()); } } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/TransitionImportReference.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/TransitionImportReference.java index 33528a9d0dd..6d4a6a85192 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/TransitionImportReference.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/TransitionImportReference.java @@ -8,7 +8,6 @@ public class TransitionImportReference extends Node { public TransitionImportReference(Transition transition) { - this.setPosition(transition.getPosition()); this.setTitle(transition.getTitle()); this.setObjectId(transition.getObjectId()); this.setImportId(transition.getImportId()); diff --git a/src/main/java/com/netgrif/application/engine/rules/config/RuleProperties.java b/src/main/java/com/netgrif/application/engine/rules/config/RuleProperties.java new file mode 100644 index 00000000000..fce6ce08387 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/rules/config/RuleProperties.java @@ -0,0 +1,15 @@ +package com.netgrif.application.engine.rules.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Data +@Configuration +@ConfigurationProperties(prefix = "rule-engine") +public class RuleProperties { + + private boolean enabled = false; + private boolean rethrowExceptions = false; + +} diff --git a/src/main/java/com/netgrif/application/engine/rules/domain/scheduled/PetriNetRuleEvaluationJob.java b/src/main/java/com/netgrif/application/engine/rules/domain/scheduled/PetriNetRuleEvaluationJob.java index 26983209336..262e4f7bef0 100644 --- a/src/main/java/com/netgrif/application/engine/rules/domain/scheduled/PetriNetRuleEvaluationJob.java +++ b/src/main/java/com/netgrif/application/engine/rules/domain/scheduled/PetriNetRuleEvaluationJob.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.rules.domain.scheduled; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.rules.domain.facts.ScheduledRuleFact; import com.netgrif.application.engine.rules.service.interfaces.IRuleEngine; @@ -28,7 +28,7 @@ public class PetriNetRuleEvaluationJob extends RuleJob { public void doExecute(JobExecutionContext context) { String netId = getInstanceId(context); log.info("Executing PetriNetRuleEvaluationJob for net " + netId + " of rule " + getRuleIdentifier(context)); - PetriNet net = petriNetService.getPetriNet(netId); + Process net = petriNetService.getPetriNet(netId); ruleEngine.evaluateRules(net, new ScheduledRuleFact(netId, getRuleIdentifier(context))); } diff --git a/src/main/java/com/netgrif/application/engine/rules/service/RuleEngine.java b/src/main/java/com/netgrif/application/engine/rules/service/RuleEngine.java index b0fb56e444f..0f0ee95ef54 100644 --- a/src/main/java/com/netgrif/application/engine/rules/service/RuleEngine.java +++ b/src/main/java/com/netgrif/application/engine/rules/service/RuleEngine.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.rules.service; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.rules.config.RuleProperties; import com.netgrif.application.engine.rules.domain.RuleRepository; import com.netgrif.application.engine.rules.domain.facts.CaseCreatedFact; import com.netgrif.application.engine.rules.domain.facts.NetImportedFact; @@ -9,11 +10,10 @@ import com.netgrif.application.engine.rules.service.interfaces.IRuleEngine; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.kie.api.runtime.KieSession; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Lookup; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.Arrays; @@ -21,14 +21,13 @@ @Slf4j @Service +@RequiredArgsConstructor public abstract class RuleEngine implements IRuleEngine { - // TODO: release/8.0.0 properties - @Value("${rule-engine.rethrow-exceptions:#{false}}") - protected boolean rethrowExceptions; + private final RuleRepository ruleRepository; + + private final RuleProperties properties; - @Autowired - private RuleRepository ruleRepository; @Lookup protected abstract KieSession ruleEngine(); @@ -49,17 +48,17 @@ public int evaluateRules(Case useCase, ScheduledRuleFact scheduledRuleFact) { } @Override - public int evaluateRules(PetriNet petriNet, NetImportedFact fact) { + public int evaluateRules(Process petriNet, NetImportedFact fact) { return evaluateWithFacts(Arrays.asList(petriNet, fact)); } @Override - public int evaluateRules(PetriNet petriNet, ScheduledRuleFact scheduledRuleFact) { + public int evaluateRules(Process petriNet, ScheduledRuleFact scheduledRuleFact) { return evaluateWithFacts(Arrays.asList(petriNet, scheduledRuleFact)); } private int evaluateWithFacts(List<Object> facts) { - if (ruleRepository.count() == 0) { + if (!properties.isEnabled() || ruleRepository.count() == 0) { return 0; } KieSession session = null; @@ -70,7 +69,7 @@ private int evaluateWithFacts(List<Object> facts) { numberOfRulesExecuted = session.fireAllRules(); } catch (Exception e) { log.error("Rule engine failure", e); - if (rethrowExceptions) { + if (properties.isRethrowExceptions()) { throw e; } } finally { diff --git a/src/main/java/com/netgrif/application/engine/rules/service/RuleEvaluationScheduleService.java b/src/main/java/com/netgrif/application/engine/rules/service/RuleEvaluationScheduleService.java index ce3486e5bca..81dfa025fc3 100644 --- a/src/main/java/com/netgrif/application/engine/rules/service/RuleEvaluationScheduleService.java +++ b/src/main/java/com/netgrif/application/engine/rules/service/RuleEvaluationScheduleService.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.rules.service; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.rules.domain.RuleRepository; import com.netgrif.application.engine.rules.domain.StoredRule; import com.netgrif.application.engine.rules.domain.scheduled.CaseRuleEvaluationJob; @@ -41,12 +41,12 @@ public Map<String, ScheduleOutcome> scheduleRuleEvaluationForCase(Case useCase, } @Override - public ScheduleOutcome scheduleRuleEvaluationForNet(PetriNet petriNet, String ruleIdentifier, TriggerBuilder<? extends Trigger> triggerBuilder) throws RuleEvaluationScheduleException { + public ScheduleOutcome scheduleRuleEvaluationForNet(Process petriNet, String ruleIdentifier, TriggerBuilder<? extends Trigger> triggerBuilder) throws RuleEvaluationScheduleException { return scheduleRuleEvaluationForNet(petriNet, Collections.singletonList(ruleIdentifier), triggerBuilder).values().iterator().next(); } @Override - public Map<String, ScheduleOutcome> scheduleRuleEvaluationForNet(PetriNet petriNet, List<String> ruleIdentifiers, TriggerBuilder<? extends Trigger> triggerBuilder) throws RuleEvaluationScheduleException { + public Map<String, ScheduleOutcome> scheduleRuleEvaluationForNet(Process petriNet, List<String> ruleIdentifiers, TriggerBuilder<? extends Trigger> triggerBuilder) throws RuleEvaluationScheduleException { Map<String, String> data = new HashMap<>(); data.put(PetriNetRuleEvaluationJob.NET_ID, petriNet.getStringId()); return scheduleRuleEvaluation(petriNet.getStringId(), data, ruleIdentifiers, triggerBuilder); diff --git a/src/main/java/com/netgrif/application/engine/rules/service/interfaces/IRuleEngine.java b/src/main/java/com/netgrif/application/engine/rules/service/interfaces/IRuleEngine.java index 08d4a4bdc1a..4d060bad91d 100644 --- a/src/main/java/com/netgrif/application/engine/rules/service/interfaces/IRuleEngine.java +++ b/src/main/java/com/netgrif/application/engine/rules/service/interfaces/IRuleEngine.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.rules.service.interfaces; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.rules.domain.facts.CaseCreatedFact; import com.netgrif.application.engine.rules.domain.facts.NetImportedFact; import com.netgrif.application.engine.rules.domain.facts.ScheduledRuleFact; @@ -16,7 +16,7 @@ public interface IRuleEngine { int evaluateRules(Case useCase, ScheduledRuleFact scheduledRuleFact); - int evaluateRules(PetriNet petriNet, NetImportedFact fact); + int evaluateRules(Process petriNet, NetImportedFact fact); - int evaluateRules(PetriNet petriNet, ScheduledRuleFact scheduledRuleFact); + int evaluateRules(Process petriNet, ScheduledRuleFact scheduledRuleFact); } diff --git a/src/main/java/com/netgrif/application/engine/rules/service/interfaces/IRuleEvaluationScheduleService.java b/src/main/java/com/netgrif/application/engine/rules/service/interfaces/IRuleEvaluationScheduleService.java index 7128290b491..812323a1c61 100644 --- a/src/main/java/com/netgrif/application/engine/rules/service/interfaces/IRuleEvaluationScheduleService.java +++ b/src/main/java/com/netgrif/application/engine/rules/service/interfaces/IRuleEvaluationScheduleService.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.rules.service.interfaces; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.rules.domain.scheduled.ScheduleOutcome; import com.netgrif.application.engine.rules.service.throwable.RuleEvaluationScheduleException; import com.netgrif.application.engine.workflow.domain.Case; @@ -16,7 +16,7 @@ public interface IRuleEvaluationScheduleService { Map<String, ScheduleOutcome> scheduleRuleEvaluationForCase(Case useCase, List<String> ruleIdentifiers, TriggerBuilder<? extends Trigger> trigger) throws RuleEvaluationScheduleException; - ScheduleOutcome scheduleRuleEvaluationForNet(PetriNet petriNet, String ruleIdentifier, TriggerBuilder<? extends Trigger> trigger) throws RuleEvaluationScheduleException; + ScheduleOutcome scheduleRuleEvaluationForNet(Process petriNet, String ruleIdentifier, TriggerBuilder<? extends Trigger> trigger) throws RuleEvaluationScheduleException; - Map<String, ScheduleOutcome> scheduleRuleEvaluationForNet(PetriNet petriNet, List<String> ruleIdentifiers, TriggerBuilder<? extends Trigger> trigger) throws RuleEvaluationScheduleException; + Map<String, ScheduleOutcome> scheduleRuleEvaluationForNet(Process petriNet, List<String> ruleIdentifiers, TriggerBuilder<? extends Trigger> trigger) throws RuleEvaluationScheduleException; } diff --git a/src/main/java/com/netgrif/application/engine/security/service/ISecurityContextService.java b/src/main/java/com/netgrif/application/engine/security/service/ISecurityContextService.java index 4dc4546efa2..956146dfc81 100644 --- a/src/main/java/com/netgrif/application/engine/security/service/ISecurityContextService.java +++ b/src/main/java/com/netgrif/application/engine/security/service/ISecurityContextService.java @@ -1,14 +1,16 @@ package com.netgrif.application.engine.security.service; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; public interface ISecurityContextService { void saveToken(String token); - void reloadSecurityContext(LoggedUser loggedUser); + void reloadSecurityContext(LoggedIdentity identity); - void forceReloadSecurityContext(LoggedUser loggedUser); + void forceReloadSecurityContext(LoggedIdentity identity); - boolean isAuthenticatedPrincipalLoggedUser(); + boolean isAuthenticatedPrincipalLoggedIdentity(); + + boolean isIdentityLogged(String identityId); } diff --git a/src/main/java/com/netgrif/application/engine/security/service/SecurityContextService.java b/src/main/java/com/netgrif/application/engine/security/service/SecurityContextService.java index 5ecba6f00d9..14aba74f08f 100644 --- a/src/main/java/com/netgrif/application/engine/security/service/SecurityContextService.java +++ b/src/main/java/com/netgrif/application/engine/security/service/SecurityContextService.java @@ -1,18 +1,20 @@ package com.netgrif.application.engine.security.service; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** + * todo javadoc everywhere * Service for managing security context object, like user resource */ @Slf4j @@ -23,11 +25,11 @@ public class SecurityContextService implements ISecurityContextService { * List containing user IDs that's state was changed during an action */ private final Set<String> cachedTokens; + private final IIdentityService identityService; - protected IUserService userService; - - protected SecurityContextService() { + protected SecurityContextService(@Lazy IIdentityService identityService) { this.cachedTokens = ConcurrentHashMap.newKeySet(); + this.identityService = identityService; } /** @@ -46,8 +48,8 @@ public void saveToken(String token) { * @param loggedUser the user whose context needs to be reloaded */ @Override - public void reloadSecurityContext(LoggedUser loggedUser) { - reloadSecurityContext(loggedUser, false); + public void reloadSecurityContext(LoggedIdentity identity) { + reloadSecurityContext(identity, false); } /** @@ -56,19 +58,8 @@ public void reloadSecurityContext(LoggedUser loggedUser) { * @param loggedUser the user whose context needs to be reloaded */ @Override - public void forceReloadSecurityContext(LoggedUser loggedUser) { - reloadSecurityContext(loggedUser, true); - } - - private void reloadSecurityContext(LoggedUser loggedUser, boolean forceRefresh) { - if (isUserLogged(loggedUser) && cachedTokens.contains(loggedUser.getId())) { - if (forceRefresh) { - loggedUser = userService.findById(loggedUser.getId()).transformToLoggedUser(); - } - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loggedUser, SecurityContextHolder.getContext().getAuthentication().getCredentials(), loggedUser.getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(token); - clearToken(loggedUser.getId()); - } + public void forceReloadSecurityContext(LoggedIdentity identity) { + reloadSecurityContext(identity, true); } /** @@ -77,36 +68,60 @@ private void reloadSecurityContext(LoggedUser loggedUser, boolean forceRefresh) * @return true if the SecurityContext exists and is of type LoggedUser */ @Override - public boolean isAuthenticatedPrincipalLoggedUser() { - return SecurityContextHolder.getContext().getAuthentication() != null && SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof LoggedUser; + public boolean isAuthenticatedPrincipalLoggedIdentity() { + return SecurityContextHolder.getContext().getAuthentication() != null + && SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof LoggedIdentity; } /** - * Removes token from cache if the state of context object was updated + * Checks whether the user is logged in * - * @param token the token string to be removed from cache + * @param identity the user that is needed to be checked + * @return true if logged user is in the security context */ - private void clearToken(String token) { - if (cachedTokens.contains(token)) - this.cachedTokens.remove(token); + @Override + public boolean isIdentityLogged(String identityId) { + return isAuthenticatedPrincipalLoggedIdentity() + && ((LoggedIdentity) SecurityContextHolder.getContext().getAuthentication().getPrincipal()) + .getIdentityId().equals(identityId); + } + + private void reloadSecurityContext(LoggedIdentity identity, boolean forceRefresh) { + if (isIdentityLogged(identity.getIdentityId()) && cachedTokens.contains(identity.getIdentityId())) { + if (forceRefresh) { + identity = updateSessionFromDatabase(identity); + } + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(identity, + SecurityContextHolder.getContext().getAuthentication().getCredentials(), identity.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(token); + clearToken(identity.getIdentityId()); + } } /** - * Checks whether the user is logged in - * - * @param loggedUser the user that is needed to be checked - * @return true if logged user is in the security context - */ - private boolean isUserLogged(LoggedUser loggedUser) { - if (isAuthenticatedPrincipalLoggedUser()) - return ((LoggedUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId().equals(loggedUser.getId()); - else - return false; + * todo javadoc + * */ + private LoggedIdentity updateSessionFromDatabase(LoggedIdentity identity) { + Optional<Identity> identityOpt = identityService.findById(identity.getIdentityId()); + if (identityOpt.isPresent()) { + String activeActorId = identity.getActiveActorId(); + identity = identityOpt.get().toSession(); + if (activeActorId != null) { + identity.setActiveActorId(activeActorId); + } + return identity; + } + return identity; } - @Autowired - @Lazy - public void setUserService(IUserService userService) { - this.userService = userService; + /** + * Removes token from cache if the state of context object was updated + * + * @param token the token string to be removed from cache + */ + private void clearToken(String token) { + if (cachedTokens.contains(token)) { + this.cachedTokens.remove(token); + } } } diff --git a/src/main/java/com/netgrif/application/engine/settings/domain/Preferences.java b/src/main/java/com/netgrif/application/engine/settings/domain/Preferences.java index 506ce2da146..4b66463e8eb 100644 --- a/src/main/java/com/netgrif/application/engine/settings/domain/Preferences.java +++ b/src/main/java/com/netgrif/application/engine/settings/domain/Preferences.java @@ -12,7 +12,7 @@ import java.util.Map; /** - * User application preferences. Contains: + * Identity application preferences. Contains: * <ul> * <li>locale</li> * <li>task filters for each task view</li> @@ -26,7 +26,7 @@ public class Preferences implements Serializable { @Id - private String userId; + private String identityId; private String locale; @@ -50,8 +50,8 @@ public class Preferences implements Serializable { @Field private Map<String, List<String>> headers = new HashMap<>(); - public Preferences(String userId) { - this.userId = userId; + public Preferences(String identityId) { + this.identityId = identityId; this.drawerWidth = 200; } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/settings/domain/PreferencesRepository.java b/src/main/java/com/netgrif/application/engine/settings/domain/PreferencesRepository.java index af89d3ba265..e673e46aef5 100644 --- a/src/main/java/com/netgrif/application/engine/settings/domain/PreferencesRepository.java +++ b/src/main/java/com/netgrif/application/engine/settings/domain/PreferencesRepository.java @@ -3,8 +3,10 @@ import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface PreferencesRepository extends MongoRepository<Preferences, Long> { - Preferences findByUserId(String id); + Optional<Preferences> findByIdentityId(String id); } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/settings/service/IPreferencesService.java b/src/main/java/com/netgrif/application/engine/settings/service/IPreferencesService.java index 1d90248ddfd..71ab8bfdad0 100644 --- a/src/main/java/com/netgrif/application/engine/settings/service/IPreferencesService.java +++ b/src/main/java/com/netgrif/application/engine/settings/service/IPreferencesService.java @@ -2,9 +2,11 @@ import com.netgrif.application.engine.settings.domain.Preferences; +import java.util.Optional; + public interface IPreferencesService { - Preferences get(String userId); + Optional<Preferences> get(String identityId); Preferences save(Preferences preferences); } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/settings/service/PreferencesService.java b/src/main/java/com/netgrif/application/engine/settings/service/PreferencesService.java index 3d2f8e7dbc2..09bc00c363e 100644 --- a/src/main/java/com/netgrif/application/engine/settings/service/PreferencesService.java +++ b/src/main/java/com/netgrif/application/engine/settings/service/PreferencesService.java @@ -2,18 +2,20 @@ import com.netgrif.application.engine.settings.domain.Preferences; import com.netgrif.application.engine.settings.domain.PreferencesRepository; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.Optional; + @Service +@RequiredArgsConstructor public class PreferencesService implements IPreferencesService { - @Autowired - private PreferencesRepository repository; + private final PreferencesRepository repository; @Override - public Preferences get(String userId) { - return repository.findByUserId(userId); + public Optional<Preferences> get(String identityId) { + return repository.findByIdentityId(identityId); } @Override diff --git a/src/main/java/com/netgrif/application/engine/transaction/NaeTransaction.java b/src/main/java/com/netgrif/application/engine/transaction/NaeTransaction.java new file mode 100644 index 00000000000..02e2b2d208e --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/transaction/NaeTransaction.java @@ -0,0 +1,181 @@ +package com.netgrif.application.engine.transaction; + +import groovy.lang.Closure; +import lombok.Builder; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.mongodb.MongoTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.TransactionTimedOutException; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.support.*; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionDelegate; + +import java.util.Date; + +import static org.springframework.transaction.support.TransactionSynchronization.STATUS_COMMITTED; +import static org.springframework.transaction.support.TransactionSynchronization.STATUS_ROLLED_BACK; + + +@Data +@Slf4j +@Builder +public class NaeTransaction { + + /** + * Timeout for the transaction in milliseconds. When the timeout is reached, transaction fails on commit. + * */ + @Builder.Default + private int timeout = TransactionDefinition.TIMEOUT_DEFAULT; + /** + * If set to true, new transaction is created in any situation (uses {@link Propagation#REQUIRES_NEW}). If set to + * false, transaction is created only if none exists (uses {@link Propagation#REQUIRED}). + * */ + @Builder.Default + private boolean forceCreation = false; + /** + * Transaction code to be executed under transaction. + * */ + private Closure<?> event; + /** + * Return value of the {@link #event} + * */ + private Object resultOfEvent; + /** + * Callback, that is called when {@link NaeTransaction#event} is successful. + * */ + private Closure<?> onCommit; + /** + * Callback, that is called when {@link NaeTransaction#event} fails. The closure can contain input attribute. If so, + * the input attribute is initialized by the subject exception ({@link NaeTransaction#onEventException}) + * */ + private Closure<?> onRollBack; + + private Exception onCallBackException; + private Exception onEventException; + @Builder.Default + private Propagation propagation = Propagation.REQUIRED; + private Date deadline; + private boolean wasRolledBack; + + /** + * Singleton bean of Mongo transaction manager provided from {@link ActionDelegate#getTransactionManager} + * */ + private final MongoTransactionManager transactionManager; + + /** + * Does additional setups for transaction by {@link TransactionTemplate} and executes provided {@link NaeTransaction#event}. + * <br> + * If the execution is successful callback {@link NaeTransaction#onCommit} is called. Otherwise {@link NaeTransaction#onRollBack} + * is called. If any of the callback fails, the exception is thrown and saved in {@link NaeTransaction#onEventException} + * */ + public void begin() { + TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); + transactionTemplate.setPropagationBehavior(propagation.value()); + setTimeoutInMillis(timeout); + + transactionTemplate.execute(new TransactionCallbackWithoutResult() { + protected void doInTransactionWithoutResult(TransactionStatus status) { + try { + registerTransactionCallBacks(); + resultOfEvent = event.call(); + throwIfDeadlineReached(); // Transaction API does not check the timeout declared in transaction template + } catch (Exception rethrow) { + onEventException = rethrow; + throw rethrow; + } + } + }); + } + + /** + * Registers callbacks for the active transaction. Must be called under active transaction. Callbacks are registered + * by {@link TransactionSynchronizationManager#registerSynchronization(TransactionSynchronization)}. If any of the + * callbacks fails the exception is not thrown. It's saved in {@link NaeTransaction#onCallBackException}. + * */ + private void registerTransactionCallBacks() { + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization(){ + public void afterCompletion(int status) { + if (canCallOnCommit(status)) { + runTransactionCallBack(onCommit); + } else if (canCallOnRollBack(status)) { + wasRolledBack = true; + if (onEventException != null) { + onRollBack = onRollBack.curry(onEventException); + } + runTransactionCallBack(onRollBack); + } + } + }); + } + + private boolean canCallOnCommit(int status) { + return status == STATUS_COMMITTED && onCommit != null; + } + + private boolean canCallOnRollBack(int status) { + return status == STATUS_ROLLED_BACK && onRollBack != null; + } + + /** + * Runs the provided callback. If the callback fails, the exception is saved in {@link NaeTransaction#onCallBackException} + * and thrown. + * + * @param callBack callback to be executed + * */ + private void runTransactionCallBack(Closure<?> callBack) { + try { + callBack.run(); + } catch (Exception e) { + // Transaction manager API swallows the exception + onCallBackException = e; + throw e; + } + } + + /** + * Initializes the {@link NaeTransaction#deadline} field by the provided timeout in milliseconds. + * + * @param millis timeout in milliseconds. Can be {@link TransactionDefinition#TIMEOUT_DEFAULT} or positive number + * */ + private void setTimeoutInMillis(long millis) throws IllegalArgumentException { + if (timeout == TransactionDefinition.TIMEOUT_DEFAULT) { + return; + } + if (timeout <= 0) { + throw new IllegalArgumentException(String.format("Timeout can be %s or positive number to represent millis.", + TransactionDefinition.TIMEOUT_DEFAULT)); + } + this.deadline = new Date(System.currentTimeMillis() + millis); + } + + /** + * Throws the {@link TransactionTimedOutException} if the {@link NaeTransaction#deadline} is reached + */ + private void throwIfDeadlineReached() throws TransactionTimedOutException { + if (this.deadline == null) { + return; + } + long timeToLive = this.deadline.getTime() - System.currentTimeMillis(); + if (timeToLive <= 0) { + throw new TransactionTimedOutException("Transaction timed out: deadline was " + this.deadline); + } + } + + /** + * Builder extension of the {@link Builder} implementation for {@link }. Containing additional logic over the native builder + * implementation + * */ + public static class NaeTransactionBuilder { + public NaeTransactionBuilder forceCreation(boolean forceCreation) { + this.propagation$set = true; + this.propagation$value = forceCreation ? Propagation.REQUIRES_NEW : Propagation.REQUIRED; + + this.forceCreation$set = true; + this.forceCreation$value = forceCreation; + + return this; + } + } +} diff --git a/src/main/java/com/netgrif/application/engine/transaction/configuration/NaeTransactionProperties.java b/src/main/java/com/netgrif/application/engine/transaction/configuration/NaeTransactionProperties.java new file mode 100644 index 00000000000..81643889ddc --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/transaction/configuration/NaeTransactionProperties.java @@ -0,0 +1,16 @@ +package com.netgrif.application.engine.transaction.configuration; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Data +@Configuration +@ConfigurationProperties(prefix = "nae.transaction") +public class NaeTransactionProperties { + private boolean createCaseTransactional = true; + private boolean deleteCaseTransactional = true; + private boolean setDataTransactional = true; + private boolean getDataTransactional = true; + private boolean taskEventTransactional = true; +} diff --git a/src/main/java/com/netgrif/application/engine/utils/UniqueKeyMapWrapper.java b/src/main/java/com/netgrif/application/engine/utils/UniqueKeyMapWrapper.java new file mode 100644 index 00000000000..13427e4566e --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/utils/UniqueKeyMapWrapper.java @@ -0,0 +1,79 @@ +package com.netgrif.application.engine.utils; + +import lombok.Getter; +import lombok.Setter; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.function.BiConsumer; + + +/** + * Extends {@link LinkedHashMap} with a feature to throw {@link IllegalArgumentException} if the key already exists when + * putting the key using {@link UniqueKeyMapWrapper#put(String, Object)} + */ +public class UniqueKeyMapWrapper<V> { + + @Setter + @Getter + private LinkedHashMap<String, V> map; + + public UniqueKeyMapWrapper() { + this.map = new LinkedHashMap<>(); + } + + public UniqueKeyMapWrapper(UniqueKeyMapWrapper<V> m) { + this.map = new LinkedHashMap<>(m.map); + } + + public V put(String key, V value) throws IllegalArgumentException { + V previousValue = putIfAbsent(key, value); + if (previousValue != null) { + throw new IllegalArgumentException("Key is not unique: " + key); + } + return null; + } + + public boolean containsKey(String key) { + return this.map.containsKey(key); + } + + public V get(String key) { + return this.map.get(key); + } + + public V getOrDefault(String key, V defaultValue) { + return this.map.getOrDefault(key, defaultValue); + } + + public Collection<V> values() { + return this.map.values(); + } + + public void forEach(BiConsumer<String, V> action) { + this.map.forEach(action); + } + + public Set<Map.Entry<String, V>> entrySet() { + return this.map.entrySet(); + } + + public void remove(String key) { + this.map.remove(key); + } + + public int size() { + return this.map.size(); + } + + @Override + public UniqueKeyMapWrapper<V> clone() { + return new UniqueKeyMapWrapper<>(this); + } + + private V putIfAbsent(String key, V value) { + return this.map.putIfAbsent(key, value); + } +} diff --git a/src/main/java/com/netgrif/application/engine/validations/ValidationRegistry.java b/src/main/java/com/netgrif/application/engine/validations/ValidationRegistry.java new file mode 100644 index 00000000000..e4a9c1457c4 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/validations/ValidationRegistry.java @@ -0,0 +1,32 @@ +package com.netgrif.application.engine.validations; + +import groovy.lang.Closure; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Component +public final class ValidationRegistry { + + private final Map<String, Closure<Boolean>> validationsMap = new ConcurrentHashMap<>(); + + public Closure<Boolean> addValidation(String name, Closure<Boolean> closure) { + if (validationsMap.containsKey(name)) { + throw new IllegalArgumentException("Validation with name " + name + " already exists."); + } + return validationsMap.put(name, closure); + } + + public Closure<Boolean> getValidation(String name) { + return validationsMap.get(name); + } + + public Closure<Boolean> removeValidation(String name) { + return validationsMap.remove(name); + } + + public void removeAllValidations() { validationsMap.clear(); } +} diff --git a/src/main/java/com/netgrif/application/engine/validations/ValidationService.java b/src/main/java/com/netgrif/application/engine/validations/ValidationService.java new file mode 100644 index 00000000000..c043eb06820 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/validations/ValidationService.java @@ -0,0 +1,78 @@ +package com.netgrif.application.engine.validations; + +import com.netgrif.application.engine.event.IGroovyShellFactory; +import com.netgrif.application.engine.petrinet.domain.Transition; +import com.netgrif.application.engine.petrinet.domain.dataset.Field; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ValidationExecutioner; +import com.netgrif.application.engine.validations.interfaces.IValidationService; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.DataFieldBehavior; +import groovy.lang.Closure; +import lombok.extern.slf4j.Slf4j; +import org.codehaus.groovy.control.CompilationFailedException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class ValidationService implements IValidationService { + + private final ValidationRegistry validationRegistry; + private final ValidationExecutioner validationExecutioner; + private final IGroovyShellFactory shellFactory; + + @Autowired + public ValidationService(ValidationRegistry validationRegistry, ValidationExecutioner validationExecutioner, IGroovyShellFactory shellFactory) { + this.validationRegistry = validationRegistry; + this.validationExecutioner = validationExecutioner; + this.shellFactory = shellFactory; + } + + @Override + public void validateTransition(Case useCase, Transition transition) { + transition.getDataSet().keySet().forEach(fieldId -> { + Field<?> field = useCase.getDataSet().get(fieldId); + if (null == field || isNullAndOptional(field, transition.getImportId())) { + return; + } + validationExecutioner.execute(useCase, field); + }); + } + + @Override + public void validateField(Case useCase, Field<?> field) { + validationExecutioner.execute(useCase, field); + } + + @Override + public void registerValidation(String name, String definition) throws ClassCastException, CompilationFailedException { + if (definition == null) { + throw new IllegalArgumentException("Definition cannot be empty."); + } + Closure<Boolean> code = (Closure<Boolean>) this.shellFactory.getGroovyShell().evaluate("{" + definition + "}"); + validationRegistry.addValidation(name, code); + } + + @Override + public Closure<Boolean> getValidation(String name) { + return validationRegistry.getValidation(name); + } + + @Override + public void unregisterValidation(String name) { + validationRegistry.removeValidation(name); + } + + @Override + public void clearValidations() { + validationRegistry.removeAllValidations(); + } + + private boolean isNullAndOptional(Field<?> field, String transitionId) { + DataFieldBehavior behavior = field.getBehaviors().get(transitionId); + if (behavior == null) { + return true; + } + return !behavior.isRequired() && field.getRawValue() == null; + } +} diff --git a/src/main/java/com/netgrif/application/engine/validations/interfaces/IValidationService.java b/src/main/java/com/netgrif/application/engine/validations/interfaces/IValidationService.java new file mode 100644 index 00000000000..8ca9f08d7e6 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/validations/interfaces/IValidationService.java @@ -0,0 +1,22 @@ +package com.netgrif.application.engine.validations.interfaces; + +import com.netgrif.application.engine.petrinet.domain.Transition; +import com.netgrif.application.engine.petrinet.domain.dataset.Field; +import com.netgrif.application.engine.workflow.domain.Case; +import groovy.lang.Closure; +import org.codehaus.groovy.control.CompilationFailedException; + +public interface IValidationService { + + void validateTransition(Case useCase, Transition transition); + + void validateField(Case useCase, Field<?> field); + + void registerValidation(String name, String definition) throws ClassCastException, CompilationFailedException; + + Closure<Boolean> getValidation(String name); + + void unregisterValidation(String name); + + void clearValidations(); +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/Case.java b/src/main/java/com/netgrif/application/engine/workflow/domain/Case.java index 48cb9e903f5..e17ba44e5b2 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/Case.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/Case.java @@ -1,15 +1,16 @@ package com.netgrif.application.engine.workflow.domain; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.netgrif.application.engine.auth.domain.Author; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.authorization.domain.permissions.AccessPermissions; +import com.netgrif.application.engine.petrinet.domain.PetriNetIdentifier; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.dataset.Field; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission; +import com.netgrif.application.engine.authorization.domain.permissions.CasePermission; import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; import com.querydsl.core.annotations.PropertyType; import com.querydsl.core.annotations.QueryType; import lombok.AccessLevel; -import lombok.Getter; +import lombok.Data; import lombok.Setter; import org.bson.types.ObjectId; import org.springframework.data.annotation.Id; @@ -20,14 +21,12 @@ import javax.validation.constraints.NotNull; import java.io.Serializable; -import java.security.SecureRandom; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; +@Data @Document -@Getter -@Setter public class Case implements Serializable { private static final long serialVersionUID = 3687481049847498422L; @@ -35,27 +34,25 @@ public class Case implements Serializable { @Id @Setter(AccessLevel.NONE) private ObjectId id; - private String uriNodeId; @LastModifiedDate private LocalDateTime lastModified; - @Indexed - @Setter(AccessLevel.NONE) - private String visualId; @NotNull private ObjectId petriNetObjectId; @JsonIgnore @Transient @QueryType(PropertyType.NONE) - private PetriNet petriNet; + private Process process; @NotNull @Indexed private String processIdentifier; - @org.springframework.data.mongodb.core.mapping.Field("activePlaces") + /** + * Contains identifiers of super petri nets. The last element is the closest parent, the first is the furthest parent. + * */ + private List<PetriNetIdentifier> parentPetriNetIdentifiers; @JsonIgnore private Map<String, Integer> activePlaces = new HashMap<>(); @NotNull private String title; - private String color; private String icon; private LocalDateTime creationDate; @JsonIgnore @@ -70,105 +67,80 @@ public class Case implements Serializable { @QueryType(PropertyType.NONE) private List<Field<?>> immediateData = new ArrayList<>(); @Indexed - private Author author; + private String authorId; @JsonIgnore @QueryType(PropertyType.NONE) private Map<String, Integer> consumedTokens = new HashMap<>(); @Indexed private Map<String, TaskPair> tasks = new HashMap<>(); - // TODO: release/8.0.0 review json ignore and refactor to common Permission class - private Set<String> enabledRoles = new HashSet<>(); - //@JsonIgnore TODO: NAE-1866 refactor permission to be used only on backend - private Map<String, Map<ProcessRolePermission, Boolean>> permissions = new HashMap<>(); - //@JsonIgnore TODO: NAE-1866 refactor permission to be used only on backend - private Map<String, Map<ProcessRolePermission, Boolean>> userRefs = new HashMap<>(); - //@JsonIgnore TODO: NAE-1866 refactor permission to be used only on backend - private Map<String, Map<ProcessRolePermission, Boolean>> users = new HashMap<>(); - //@JsonIgnore TODO: NAE-1866 refactor permission to be used only on backend - private List<String> viewRoles = new ArrayList<>(); - //@JsonIgnore TODO: NAE-1866 refactor permission to be used only on backend - private List<String> viewUserRefs = new ArrayList<>(); - //@JsonIgnore TODO: NAE-1866 refactor permission to be used only on backend - private List<String> viewUsers = new ArrayList<>(); - //@JsonIgnore TODO: NAE-1866 refactor permission to be used only on backend - private List<String> negativeViewRoles = new ArrayList<>(); - //@JsonIgnore TODO: NAE-1866 refactor permission to be used only on backend - private List<String> negativeViewUsers = new ArrayList<>(); - private Map<String, String> tags = new HashMap<>(); + private AccessPermissions<CasePermission> processRolePermissions = new AccessPermissions<>(); + private AccessPermissions<CasePermission> caseRolePermissions = new AccessPermissions<>(); + private Map<String, String> properties = new HashMap<>(); + + private String uriNodeId; public Case() { id = new ObjectId(); + // TODO: release/8.0.0 spring auditing + creationDate = LocalDateTime.now(); } - public Case(PetriNet petriNet) { + public Case(Process petriNet) { this(); - this.petriNet = petriNet; + this.process = petriNet; petriNetObjectId = petriNet.getObjectId(); processIdentifier = petriNet.getIdentifier(); + parentPetriNetIdentifiers = new ArrayList<>(petriNet.getParentIdentifiers()); activePlaces = petriNet.getActivePlaces(); - visualId = generateVisualId(); - enabledRoles = petriNet.getRoles().keySet(); - negativeViewRoles.addAll(petriNet.getNegativeViewRoles()); icon = petriNet.getIcon(); - userRefs = petriNet.getUserRefs(); - - permissions = petriNet.getPermissions().entrySet().stream() - .filter(role -> role.getValue().containsKey(ProcessRolePermission.DELETE) || role.getValue().containsKey(ProcessRolePermission.VIEW)) - .map(role -> { - Map<ProcessRolePermission, Boolean> permissionMap = new HashMap<>(); - if (role.getValue().containsKey(ProcessRolePermission.DELETE)) - permissionMap.put(ProcessRolePermission.DELETE, role.getValue().get(ProcessRolePermission.DELETE)); - if (role.getValue().containsKey(ProcessRolePermission.VIEW)) { - permissionMap.put(ProcessRolePermission.VIEW, role.getValue().get(ProcessRolePermission.VIEW)); - } - return new AbstractMap.SimpleEntry<>(role.getKey(), permissionMap); - }) - .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue)); - resolveViewRoles(); - resolveViewUserRefs(); + processRolePermissions = new AccessPermissions<>(petriNet.getProcessRolePermissions(), Set.of(CasePermission.CREATE)); + caseRolePermissions = new AccessPermissions<>(); } public String getStringId() { return id.toString(); } - public void resolveImmediateDataFields() { - immediateData = dataSet.getFields().values().stream().filter(Field::isImmediate).collect(Collectors.toList()); - immediateDataFields = immediateData.stream().map(Field::getStringId).collect(Collectors.toCollection(LinkedHashSet::new)); + /** + * todo javadoc + * */ + public void addProcessRolePermissions(String roleId, Map<CasePermission, Boolean> permissions) { + this.processRolePermissions.addPermissions(roleId, permissions); } - public void setColor(String color) { - // TODO: release/8.0.0 - this.color = color == null || color.isEmpty() ? "color-fg-fm-500" : color; + /** + * todo javadoc + * */ + public void addProcessRolePermissions(AccessPermissions<CasePermission> rolesAndPermissions) { + this.processRolePermissions.addPermissions(rolesAndPermissions); } - // TODO: release/8.0.0 - // populateDataSet -/*if (field.getComponent() != null) { - this.dataSet.get(key).setComponent(field.getComponent()); - } - */ - private String generateVisualId() { - SecureRandom random = new SecureRandom(); - int n = id.getTimestamp() + random.nextInt(99999999); - if (this.title != null) { - n += title.length(); - } - if (this.petriNet != null) { - return petriNet.getInitials() + "-" + n; - } - return n + ""; + /** + * todo javadoc + * */ + public void addCaseRolePermissions(String roleId, Map<CasePermission, Boolean> permissions) { + this.caseRolePermissions.addPermissions(roleId, permissions); + } + + /** + * todo javadoc + * */ + public void addCaseRolePermissions(AccessPermissions<CasePermission> rolesAndPermissions) { + this.caseRolePermissions.addPermissions(rolesAndPermissions); + } + + public void resolveImmediateDataFields() { + immediateData = dataSet.getFields().values().stream() + .filter((field) -> field.getImmediate() != null && field.getImmediate()) + .collect(Collectors.toList()); + immediateDataFields = immediateData.stream().map(Field::getStringId).collect(Collectors.toCollection(LinkedHashSet::new)); } public ObjectId getTaskId(String transitionId) { - if (transitionId == null) { - throw new IllegalArgumentException("TransitionId cannot be null"); - } - TaskPair taskPair = tasks.get(transitionId); - if (taskPair == null) { + if (transitionId == null || !tasks.containsKey(transitionId)) { throw new IllegalArgumentException("Case does not have task with transitionId [" + transitionId + "]"); } - return taskPair.getTaskId(); + return tasks.get(transitionId).getTaskId(); } public String getTaskStringId(String transitionId) { @@ -179,58 +151,26 @@ public void addTask(Task task) { this.tasks.put(task.getTransitionId(), new TaskPair(task)); } + public void addTasks(Collection<Task> tasks) { + if (tasks == null) { + return; + } + tasks.forEach(this::addTask); + } + public void removeTasks(List<Task> tasks) { tasks.forEach(task -> this.tasks.remove(task.getTransitionId()) ); } - public String getPetriNetId() { - return petriNetObjectId.toString(); - } - - public void addUsers(Set<String> userIds, Map<ProcessRolePermission, Boolean> permissions) { - userIds.forEach(userId -> { - if (users.containsKey(userId) && users.get(userId) != null) { - compareExistingUserPermissions(userId, new HashMap<>(permissions)); - } else { - users.put(userId, new HashMap<>(permissions)); - } - }); - } - - public void resolveViewRoles() { - this.viewRoles.clear(); - this.permissions.forEach((role, perms) -> { - if (perms.containsKey(ProcessRolePermission.VIEW) && perms.get(ProcessRolePermission.VIEW)) { - viewRoles.add(role); - } - }); - } - - public void resolveViewUserRefs() { - this.viewUserRefs.clear(); - this.userRefs.forEach((userRef, perms) -> { - if (perms.containsKey(ProcessRolePermission.VIEW) && perms.get(ProcessRolePermission.VIEW)) { - viewUserRefs.add(userRef); - } - }); + public void updateTask(Task task) { + TaskPair taskPair = tasks.get(task.getTransitionId()); + taskPair.setState(task.getState()); + taskPair.setAssigneeId(task.getAssigneeId()); } - public void resolveViewUsers() { - this.viewUsers.clear(); - this.users.forEach((user, perms) -> { - if (perms.containsKey(ProcessRolePermission.VIEW) && perms.get(ProcessRolePermission.VIEW)) { - viewUsers.add(user); - } - }); - } - - private void compareExistingUserPermissions(String userId, Map<ProcessRolePermission, Boolean> permissions) { - permissions.forEach((id, perm) -> { - if ((users.containsKey(userId) && !users.get(userId).containsKey(id)) || (users.containsKey(userId) && users.get(userId).containsKey(id) && users.get(userId).get(id))) { - users.get(userId).put(id, perm); - } - }); + public String getPetriNetId() { + return petriNetObjectId.toString(); } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/CaseParams.java b/src/main/java/com/netgrif/application/engine/workflow/domain/CaseParams.java new file mode 100644 index 00000000000..f7f58bcf50e --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/CaseParams.java @@ -0,0 +1,50 @@ +package com.netgrif.application.engine.workflow.domain; + +import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.annotation.Nullable; +import java.util.Map; + +import static org.junit.Assert.assertNotNull; + +@Getter +@NoArgsConstructor +public abstract class CaseParams { + + protected Map<String, String> properties; + + public CaseParams(@Nullable Map<String, String> properties) { + this.properties = properties; + } + + public void addProperty(String key, String value) { + if (this.properties == null) { + return; + } + assertNotNull(key); + this.properties.put(key, value); + } + + public void removeProperty(String key) { + if (this.properties == null) { + return; + } + this.properties.remove(key); + } + + public String getProperty(String key) { + if (this.properties == null) { + return null; + } + return this.properties.get(key); + } + + /** + * todo javadoc + * */ + public abstract DataSet toDataSet(); + + public abstract String targetProcessIdentifier(); +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/Filter.java b/src/main/java/com/netgrif/application/engine/workflow/domain/Filter.java index 375b8d2cdb7..087d3a83d79 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/Filter.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/Filter.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.workflow.domain; -import com.netgrif.application.engine.auth.domain.Author; +import com.netgrif.application.engine.authorization.domain.User; import com.netgrif.application.engine.petrinet.domain.I18nString; import lombok.Data; import org.bson.types.ObjectId; @@ -33,7 +33,7 @@ public class Filter { private Integer visibility; - private Author author; + private User author; // todo: release/8.0.0 Actor type leads to compilation error private LocalDateTime created; @@ -47,7 +47,7 @@ public Filter() { this.created = LocalDateTime.now(); } - public Filter(I18nString title, I18nString description, Integer visibility, Author author, String type, String query, MergeFilterOperation mergeOperation) { + public Filter(I18nString title, I18nString description, Integer visibility, User author, String type, String query, MergeFilterOperation mergeOperation) { this(); this.title = title; this.description = description; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/IllegalArgumentWithChangedFieldsException.java b/src/main/java/com/netgrif/application/engine/workflow/domain/IllegalArgumentWithChangedFieldsException.java index 47d5a184d3b..c5d50e77698 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/IllegalArgumentWithChangedFieldsException.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/IllegalArgumentWithChangedFieldsException.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.workflow.domain; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/SystemCase.java b/src/main/java/com/netgrif/application/engine/workflow/domain/SystemCase.java new file mode 100644 index 00000000000..817b4e8719b --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/SystemCase.java @@ -0,0 +1,48 @@ +package com.netgrif.application.engine.workflow.domain; + +import javax.validation.constraints.NotNull; +import java.util.Map; + +public abstract class SystemCase { + + @NotNull + protected final Case systemCase; + + public SystemCase(Case systemCase) { + if (systemCase == null) { + throw new NullPointerException("Cannot initialize system case object. Provided case is null"); + } + CanInitializeOutcome canInitialize = canInitialize(systemCase); + if (!canInitialize.value) { + throw new IllegalArgumentException(String.format("Cannot create system case: %s", canInitialize.message)); + } + this.systemCase = systemCase; + } + + /** + * todo javadoc + * */ + protected abstract CanInitializeOutcome canInitialize(Case systemCase); + + public Case getCase() { + return this.systemCase; + } + + public String getStringId() { + return this.getCase().getStringId(); + } + + public Map<String, String> getProperties() { + return this.getCase().getProperties(); + } + + protected static class CanInitializeOutcome { + protected final String message; + protected final boolean value; + + public CanInitializeOutcome(String message, boolean value) { + this.message = message; + this.value = value; + } + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/Task.java b/src/main/java/com/netgrif/application/engine/workflow/domain/Task.java index e63f53e91b8..2a6a95f0985 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/Task.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/Task.java @@ -1,20 +1,14 @@ package com.netgrif.application.engine.workflow.domain; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.importer.model.EventType; +import com.netgrif.application.engine.authorization.domain.permissions.AccessPermissions; import com.netgrif.application.engine.importer.model.TriggerType; import com.netgrif.application.engine.petrinet.domain.I18nString; import com.netgrif.application.engine.petrinet.domain.dataset.Field; -import com.netgrif.application.engine.petrinet.domain.layout.TaskLayout; import com.netgrif.application.engine.petrinet.domain.policies.AssignPolicy; -import com.netgrif.application.engine.petrinet.domain.policies.DataFocusPolicy; import com.netgrif.application.engine.petrinet.domain.policies.FinishPolicy; -import com.netgrif.application.engine.petrinet.domain.roles.AssignedUserPermission; -import com.netgrif.application.engine.petrinet.domain.roles.RolePermission; +import com.netgrif.application.engine.authorization.domain.permissions.TaskPermission; import com.netgrif.application.engine.workflow.domain.triggers.Trigger; -import com.querydsl.core.annotations.PropertyType; -import com.querydsl.core.annotations.QueryType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -43,107 +37,51 @@ public class Task implements Serializable { @Id @Builder.Default private ObjectId id = new ObjectId(); - @Indexed private String processId; - @Indexed private String caseId; - + @Getter @Indexed private String transitionId; - @Indexed private State state = DISABLED; - - @QueryType(PropertyType.NONE) - private TaskLayout layout; - - private I18nString title; - // TODO: release/8.0.0: TaskResource concern? - private String caseColor; - // TODO: release/8.0.0: TaskResource concern? - private String caseTitle; - - private Integer priority; - @Indexed - private String userId; - - @org.springframework.data.annotation.Transient - private IUser user; - - @Builder.Default - private List<Trigger> triggers = new LinkedList<>(); - - /** - * Role ObjectId : [ RolePermission, true/false ] - */ - @Builder.Default - private Map<String, Map<RolePermission, Boolean>> roles = new HashMap<>(); + private String assigneeId; - @Builder.Default - private Map<String, Map<RolePermission, Boolean>> userRefs = new HashMap<>(); - - @Builder.Default - private Map<String, Map<RolePermission, Boolean>> users = new HashMap<>(); + private I18nString title; + @Getter + private String icon; @Builder.Default - private List<String> viewRoles = new LinkedList<>(); - + private AssignPolicy assignPolicy = AssignPolicy.MANUAL; @Builder.Default - private List<String> viewUserRefs = new LinkedList<>(); + private FinishPolicy finishPolicy = FinishPolicy.MANUAL; @Builder.Default - private List<String> viewUsers = new LinkedList<>(); + private List<Trigger> triggers = new LinkedList<>(); @Builder.Default - private List<String> negativeViewRoles = new LinkedList<>(); + private AccessPermissions<TaskPermission> processRolePermissions = new AccessPermissions<>(); @Builder.Default - private List<String> negativeViewUsers = new LinkedList<>(); + private AccessPermissions<TaskPermission> caseRolePermissions = new AccessPermissions<>(); private LocalDateTime lastAssigned; - private LocalDateTime lastFinished; - private String finishedBy; - private String transactionId; - // TODO: release/8.0.0 remove, dynamically load from dataSet - @Getter - @Setter @JsonIgnore @Builder.Default private LinkedHashSet<String> immediateDataFields = new LinkedHashSet<>(); - @Getter - @Setter @Transient @Builder.Default private List<Field<?>> immediateData = new LinkedList<>(); - private String icon; - - @Builder.Default - private AssignPolicy assignPolicy = AssignPolicy.MANUAL; - - @Builder.Default - private DataFocusPolicy dataFocusPolicy = DataFocusPolicy.MANUAL; - - @Builder.Default - private FinishPolicy finishPolicy = FinishPolicy.MANUAL; - - @Builder.Default - private Map<EventType, I18nString> eventTitles = new HashMap<>(); - - @Builder.Default - private Map<AssignedUserPermission, Boolean> assignedUserPolicy = new HashMap<>(); - private Map<String, Integer> consumedTokens = new HashMap<>(); - @Builder.Default - private Map<String, String> tags = new HashMap<>(); + private Map<String, String> properties = new HashMap<>(); public Task() { } @@ -157,42 +95,20 @@ public String getStringId() { return id.toString(); } - public String getTransitionId() { - return transitionId; - } - - public String getIcon() { - return icon; + public void addProcessRolePermissions(String roleId, Map<TaskPermission, Boolean> permissions) { + this.processRolePermissions.addPermissions(roleId, permissions); } - public void addRole(String roleId, Map<RolePermission, Boolean> permissions) { - if (roles.containsKey(roleId) && roles.get(roleId) != null) { - roles.get(roleId).putAll(permissions); - } else { - roles.put(roleId, permissions); - } + public void addProcessRolePermissions(AccessPermissions<TaskPermission> rolesAndPermissions) { + this.processRolePermissions.addPermissions(rolesAndPermissions); } - public void addNegativeViewRole(String roleId) { - negativeViewRoles.add(roleId); + public void addCaseRolePermissions(String roleId, Map<TaskPermission, Boolean> permissions) { + this.caseRolePermissions.addPermissions(roleId, permissions); } - public void addUserRef(String userRefId, Map<RolePermission, Boolean> permissions) { - userRefs.put(userRefId, permissions); - } - - public void addUsers(Set<String> userIds, Map<RolePermission, Boolean> permissions) { - userIds.forEach(userId -> { - if (users.containsKey(userId) && users.get(userId) != null) { - compareExistingUserPermissions(userId, new HashMap<>(permissions)); - } else { - users.put(userId, new HashMap<>(permissions)); - } - }); - } - - public void addAssignedUserPolicy(Map<AssignedUserPermission, Boolean> assignedUser) { - assignedUserPolicy.putAll(assignedUser); + public void addCaseRolePermissions(AccessPermissions<TaskPermission> rolesAndPermissions) { + this.caseRolePermissions.addPermissions(rolesAndPermissions); } @JsonIgnore @@ -204,17 +120,6 @@ public void addTrigger(Trigger trigger) { triggers.add(trigger); } - public void addEventTitle(EventType type, I18nString title) { - if (type == null || title == null) - return; - eventTitles.put(type, title); - } - - @JsonIgnore - public String getUserId() { - return userId; - } - // TODO: release/8.0.0 /*public String getTranslatedEventTitle(EventType assign, Locale locale) { if (eventTitles == null || !eventTitles.containsKey(assign)) @@ -229,39 +134,10 @@ public boolean isAutoTriggered() { return triggers.stream().anyMatch(trigger -> trigger != null && TriggerType.AUTO.equals(trigger.getType())); } - public void resolveViewRoles() { - this.viewRoles.clear(); - this.roles.forEach((role, perms) -> { - if (perms.containsKey(RolePermission.VIEW) && perms.get(RolePermission.VIEW)) { - viewRoles.add(role); - } - }); - } - - public void resolveViewUserRefs() { - this.viewUserRefs.clear(); - this.userRefs.forEach((userRef, perms) -> { - if (perms.containsKey(RolePermission.VIEW) && perms.get(RolePermission.VIEW)) { - viewUserRefs.add(userRef); - } - }); - } - - public void resolveViewUsers() { - this.viewUsers.clear(); - this.users.forEach((role, perms) -> { - if (perms.containsKey(RolePermission.VIEW) && perms.get(RolePermission.VIEW)) { - viewUsers.add(role); - } - }); - } - - private void compareExistingUserPermissions(String userId, Map<RolePermission, Boolean> permissions) { - // TODO: release/8.0.0 check if possible to reduce duplicated code, possible solution is to have abstraction on permissions map - permissions.forEach((id, perm) -> { - if ((users.containsKey(userId) && !users.get(userId).containsKey(id)) || (users.containsKey(userId) && users.get(userId).containsKey(id) && users.get(userId).get(id))) { - users.get(userId).put(id, perm); - } - }); + /** + * todo javadoc + * */ + public boolean hasPermissions() { + return this.processRolePermissions != null && this.processRolePermissions.isEmpty(); } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/TaskPair.java b/src/main/java/com/netgrif/application/engine/workflow/domain/TaskPair.java index 1539d91726e..91d862ac025 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/TaskPair.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/TaskPair.java @@ -6,22 +6,23 @@ import org.bson.types.ObjectId; import java.io.Serializable; +@Data @NoArgsConstructor @AllArgsConstructor -@Data public class TaskPair implements Serializable { private static final long serialVersionUID = -3865322078419904394L; private ObjectId taskId; private String transitionId; private State state; - private String userId; + private String assigneeId; public TaskPair(Task task) { this.taskId = task.getId(); this.transitionId = task.getTransitionId(); this.state = task.getState(); - this.userId = task.getUserId(); + // TODO: release/8.0.0 + this.assigneeId = task.getAssigneeId(); } public String getTaskStringId() { diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/dataoutcomes/GetDataGroupsEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/dataoutcomes/GetDataGroupsEventOutcome.java deleted file mode 100644 index 896e04ebbc4..00000000000 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/dataoutcomes/GetDataGroupsEventOutcome.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes; - -import com.netgrif.application.engine.petrinet.domain.DataGroup; -import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.TaskEventOutcome; -import lombok.Data; - -import java.util.List; - -@Data -public class GetDataGroupsEventOutcome extends TaskEventOutcome { - - private List<DataGroup> data; - - public GetDataGroupsEventOutcome(Case aCase, Task task) { - super(aCase, task); - } - - public GetDataGroupsEventOutcome(I18nString message, Case aCase, Task task) { - super(message, aCase, task); - } - - public GetDataGroupsEventOutcome(I18nString message, List<EventOutcome> outcomes, List<DataGroup> data, Case aCase, Task task) { - super(message, outcomes, aCase, task); - this.data = data; - } - - public List<DataGroup> getData() { - return data; - } - - public void setData(List<DataGroup> data) { - this.data = data; - } -} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/petrinetoutcomes/ImportPetriNetEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/petrinetoutcomes/ImportPetriNetEventOutcome.java deleted file mode 100644 index a5e94680e3b..00000000000 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/petrinetoutcomes/ImportPetriNetEventOutcome.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes; - -import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; -import lombok.Data; - -import java.util.List; - -@Data -public class ImportPetriNetEventOutcome extends PetriNetEventOutcome { - - public ImportPetriNetEventOutcome() { - } - - public ImportPetriNetEventOutcome(PetriNet net) { - super(net); - } - - public ImportPetriNetEventOutcome(I18nString message, PetriNet net) { - super(message, net); - } - - public ImportPetriNetEventOutcome(I18nString message, List<EventOutcome> outcomes, PetriNet net) { - super(message, outcomes, net); - } -} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/petrinetoutcomes/PetriNetEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/petrinetoutcomes/PetriNetEventOutcome.java deleted file mode 100644 index 135a0a2367d..00000000000 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/petrinetoutcomes/PetriNetEventOutcome.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes; - -import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; -import lombok.Data; - -import java.util.List; - -@Data -public abstract class PetriNetEventOutcome extends EventOutcome { - - private PetriNet net; - - protected PetriNetEventOutcome() { - } - - protected PetriNetEventOutcome(PetriNet net) { - this.net = net; - } - - protected PetriNetEventOutcome(I18nString message, PetriNet net) { - super(message); - this.net = net; - } - - protected PetriNetEventOutcome(I18nString message, List<EventOutcome> outcomes, PetriNet net) { - super(message, outcomes); - this.net = net; - } - - public PetriNet getNet() { - return net; - } - - public void setNet(PetriNet net) { - this.net = net; - } -} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemBody.java b/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemBody.java index 80d128439d4..e9da9effd7c 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemBody.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemBody.java @@ -1,6 +1,5 @@ package com.netgrif.application.engine.workflow.domain.menu; -import com.netgrif.application.engine.importer.model.DataType; import com.netgrif.application.engine.petrinet.domain.I18nString; import com.netgrif.application.engine.petrinet.domain.dataset.*; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionDelegate; @@ -11,10 +10,7 @@ import javax.annotation.Nullable; import java.text.Normalizer; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Class, that holds configurable attributes of menu item. In case of attribute addition, please update also diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/CreateTasksOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/CreateTasksOutcome.java new file mode 100644 index 00000000000..d50eb77a39d --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/CreateTasksOutcome.java @@ -0,0 +1,16 @@ +package com.netgrif.application.engine.workflow.domain.outcomes; + +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.Task; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.List; + +@Data +@AllArgsConstructor +public class CreateTasksOutcome { + private Case useCase; + private List<Task> tasks; + private Task autoTriggerTask; +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/DoEventTaskOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/DoEventTaskOutcome.java new file mode 100644 index 00000000000..bb8b676154e --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/DoEventTaskOutcome.java @@ -0,0 +1,14 @@ +package com.netgrif.application.engine.workflow.domain.outcomes; + +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.Task; +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class DoEventTaskOutcome { + + private Task task; + private Case useCase; +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/UpdateTaskStateOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/UpdateTaskStateOutcome.java new file mode 100644 index 00000000000..822c1392da7 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/UpdateTaskStateOutcome.java @@ -0,0 +1,12 @@ +package com.netgrif.application.engine.workflow.domain.outcomes; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class UpdateTaskStateOutcome { + + private boolean wasChanged; + private boolean mustBeExecuted; +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/EventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/EventOutcome.java similarity index 94% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/EventOutcome.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/EventOutcome.java index ba2310a190c..c97dd82e9e6 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/EventOutcome.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/EventOutcome.java @@ -1,4 +1,4 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes; import com.netgrif.application.engine.petrinet.domain.I18nString; import com.netgrif.application.engine.petrinet.domain.dataset.logic.FrontAction; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/caseoutcomes/CaseEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/caseoutcomes/CaseEventOutcome.java similarity index 65% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/caseoutcomes/CaseEventOutcome.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/caseoutcomes/CaseEventOutcome.java index 485d46fa3f7..9fbb8cfc658 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/caseoutcomes/CaseEventOutcome.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/caseoutcomes/CaseEventOutcome.java @@ -1,9 +1,9 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes; import com.netgrif.application.engine.petrinet.domain.I18nString; import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.PetriNetEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.PetriNetEventOutcome; import java.util.List; @@ -16,7 +16,7 @@ protected CaseEventOutcome() { } protected CaseEventOutcome(Case aCase) { - super(aCase.getPetriNet()); + super(aCase.getProcess()); this.aCase = aCase; } @@ -26,12 +26,12 @@ protected CaseEventOutcome(Case aCase, List<EventOutcome> outcomes) { } protected CaseEventOutcome(I18nString message, Case aCase) { - super(message, aCase.getPetriNet()); + super(message, aCase.getProcess()); this.aCase = aCase; } protected CaseEventOutcome(I18nString message, List<EventOutcome> outcomes, Case aCase) { - super(message, outcomes, aCase.getPetriNet()); + super(message, outcomes, aCase.getProcess()); this.aCase = aCase; } @@ -41,6 +41,6 @@ public Case getCase() { public void setCase(Case aCase) { this.aCase = aCase; - setNet(aCase.getPetriNet()); + setProcess(aCase.getProcess()); } } diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/caseoutcomes/CreateCaseEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/caseoutcomes/CreateCaseEventOutcome.java similarity index 79% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/caseoutcomes/CreateCaseEventOutcome.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/caseoutcomes/CreateCaseEventOutcome.java index 972f9e4757d..ee83e5cddf2 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/caseoutcomes/CreateCaseEventOutcome.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/caseoutcomes/CreateCaseEventOutcome.java @@ -1,8 +1,8 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes; import com.netgrif.application.engine.petrinet.domain.I18nString; import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; import java.util.List; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/caseoutcomes/DeleteCaseEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/caseoutcomes/DeleteCaseEventOutcome.java similarity index 78% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/caseoutcomes/DeleteCaseEventOutcome.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/caseoutcomes/DeleteCaseEventOutcome.java index 344b50a02b1..a7ed0c8b76f 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/caseoutcomes/DeleteCaseEventOutcome.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/caseoutcomes/DeleteCaseEventOutcome.java @@ -1,8 +1,8 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes; import com.netgrif.application.engine.petrinet.domain.I18nString; import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; import lombok.Data; import java.util.List; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/dataoutcomes/GetDataEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/dataoutcomes/GetDataEventOutcome.java similarity index 70% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/dataoutcomes/GetDataEventOutcome.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/dataoutcomes/GetDataEventOutcome.java index 9eba59cc505..c5b42af440e 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/dataoutcomes/GetDataEventOutcome.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/dataoutcomes/GetDataEventOutcome.java @@ -1,12 +1,11 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes; import com.netgrif.application.engine.petrinet.domain.DataRef; import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.petrinet.domain.dataset.Field; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.TaskEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.TaskEventOutcome; import lombok.Data; import java.util.List; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/dataoutcomes/SetDataEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/dataoutcomes/SetDataEventOutcome.java similarity index 76% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/dataoutcomes/SetDataEventOutcome.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/dataoutcomes/SetDataEventOutcome.java index f64439e90fe..77bdf255214 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/dataoutcomes/SetDataEventOutcome.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/dataoutcomes/SetDataEventOutcome.java @@ -1,10 +1,10 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes; import com.netgrif.application.engine.petrinet.domain.dataset.Field; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.TaskEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.TaskEventOutcome; import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; import lombok.Data; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/layoutoutcomes/GetLayoutsEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/layoutoutcomes/GetLayoutsEventOutcome.java new file mode 100644 index 00000000000..e8009ef0930 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/layoutoutcomes/GetLayoutsEventOutcome.java @@ -0,0 +1,30 @@ +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.layoutoutcomes; + +import com.netgrif.application.engine.petrinet.domain.I18nString; +import com.netgrif.application.engine.petrinet.domain.layout.LayoutContainer; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.Task; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.TaskEventOutcome; +import lombok.Data; + +import java.util.List; + +@Data +public class GetLayoutsEventOutcome extends TaskEventOutcome { + + private LayoutContainer layout; + + public GetLayoutsEventOutcome(Case aCase, Task task) { + super(aCase, task); + } + + public GetLayoutsEventOutcome(I18nString message, Case aCase, Task task) { + super(message, aCase, task); + } + + public GetLayoutsEventOutcome(I18nString message, List<EventOutcome> outcomes, LayoutContainer container, Case aCase, Task task) { + super(message, outcomes, aCase, task); + this.layout = container; + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/petrinetoutcomes/ImportPetriNetEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/petrinetoutcomes/ImportPetriNetEventOutcome.java new file mode 100644 index 00000000000..e3ec3a8c425 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/petrinetoutcomes/ImportPetriNetEventOutcome.java @@ -0,0 +1,27 @@ +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes; + +import com.netgrif.application.engine.petrinet.domain.I18nString; +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import lombok.Data; + +import java.util.List; + +@Data +public class ImportPetriNetEventOutcome extends PetriNetEventOutcome { + + public ImportPetriNetEventOutcome() { + } + + public ImportPetriNetEventOutcome(Process net) { + super(net); + } + + public ImportPetriNetEventOutcome(I18nString message, Process net) { + super(message, net); + } + + public ImportPetriNetEventOutcome(I18nString message, List<EventOutcome> outcomes, Process net) { + super(message, outcomes, net); + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/petrinetoutcomes/PetriNetEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/petrinetoutcomes/PetriNetEventOutcome.java new file mode 100644 index 00000000000..ee667a40e8a --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/petrinetoutcomes/PetriNetEventOutcome.java @@ -0,0 +1,39 @@ +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes; + +import com.netgrif.application.engine.petrinet.domain.I18nString; +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import lombok.Data; + +import java.util.List; + +@Data +public abstract class PetriNetEventOutcome extends EventOutcome { + + private Process process; + + protected PetriNetEventOutcome() { + } + + protected PetriNetEventOutcome(Process process) { + this.process = process; + } + + protected PetriNetEventOutcome(I18nString message, Process process) { + super(message); + this.process = process; + } + + protected PetriNetEventOutcome(I18nString message, List<EventOutcome> outcomes, Process process) { + super(message, outcomes); + this.process = process; + } + + public Process getProcess() { + return process; + } + + public void setProcess(Process process) { + this.process = process; + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/response/EventOutcomeWithMessage.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/response/EventOutcomeWithMessage.java similarity index 84% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/response/EventOutcomeWithMessage.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/response/EventOutcomeWithMessage.java index 95e602ab640..046f9ec272d 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/response/EventOutcomeWithMessage.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/response/EventOutcomeWithMessage.java @@ -1,6 +1,6 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.response; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; import com.netgrif.application.engine.workflow.web.responsebodies.ResponseMessage; import lombok.Data; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/response/EventOutcomeWithMessageResource.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/response/EventOutcomeWithMessageResource.java similarity index 80% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/response/EventOutcomeWithMessageResource.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/response/EventOutcomeWithMessageResource.java index ab740543f6f..4e392cc21ef 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/response/EventOutcomeWithMessageResource.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/response/EventOutcomeWithMessageResource.java @@ -1,6 +1,6 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.response; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; import org.springframework.hateoas.EntityModel; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/AssignTaskEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/AssignTaskEventOutcome.java similarity index 75% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/AssignTaskEventOutcome.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/AssignTaskEventOutcome.java index 03e403ec311..feaa3f26d54 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/AssignTaskEventOutcome.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/AssignTaskEventOutcome.java @@ -1,8 +1,8 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; import lombok.Data; import java.util.List; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/CancelTaskEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/CancelTaskEventOutcome.java similarity index 75% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/CancelTaskEventOutcome.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/CancelTaskEventOutcome.java index 022f901a20a..52862b1dd9a 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/CancelTaskEventOutcome.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/CancelTaskEventOutcome.java @@ -1,8 +1,8 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; import lombok.Data; import java.util.List; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/DelegateTaskEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/DelegateTaskEventOutcome.java similarity index 75% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/DelegateTaskEventOutcome.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/DelegateTaskEventOutcome.java index fbecc39e2d0..87a97589508 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/DelegateTaskEventOutcome.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/DelegateTaskEventOutcome.java @@ -1,8 +1,8 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; import lombok.Data; import java.util.List; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/FinishTaskEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/FinishTaskEventOutcome.java similarity index 75% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/FinishTaskEventOutcome.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/FinishTaskEventOutcome.java index 9fd45065606..f3f2725fbf7 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/FinishTaskEventOutcome.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/FinishTaskEventOutcome.java @@ -1,8 +1,8 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; import lombok.Data; import java.util.List; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/TaskEventOutcome.java b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/TaskEventOutcome.java similarity index 74% rename from src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/TaskEventOutcome.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/TaskEventOutcome.java index 2c605138fdc..9228da6e699 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/eventoutcomes/taskoutcomes/TaskEventOutcome.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/outcomes/eventoutcomes/taskoutcomes/TaskEventOutcome.java @@ -1,10 +1,10 @@ -package com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes; +package com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes; import com.netgrif.application.engine.petrinet.domain.I18nString; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CaseEventOutcome; import lombok.Data; import lombok.Getter; diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/params/CreateCaseParams.java b/src/main/java/com/netgrif/application/engine/workflow/domain/params/CreateCaseParams.java new file mode 100644 index 00000000000..f13f3663fdc --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/params/CreateCaseParams.java @@ -0,0 +1,55 @@ +package com.netgrif.application.engine.workflow.domain.params; + +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.workflow.domain.Case; +import lombok.Builder; +import lombok.Data; +import org.springframework.context.i18n.LocaleContextHolder; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.function.Function; + + +@Data +@Builder(builderMethodName = "with") +public class CreateCaseParams { + + private String processId; + private String processIdentifier; + private Process process; + private String title; + private Function<Case, String> makeTitle; + private String authorId; + @Builder.Default + private Locale locale = LocaleContextHolder.getLocale(); + private Boolean isTransactional; + @Builder.Default + private Map<String, String> params = new HashMap<>(); + + public static class CreateCaseParamsBuilder { + /** + * Sets the {@link #title} and {@link #makeTitle} as well + * */ + public CreateCaseParamsBuilder title(String title) { + this.title = title; + if (title != null) { + this.makeTitle = (u) -> title; + } else { + this.makeTitle = null; + } + return this; + } + + /** + * Sets the {@link #process} as clone, {@link #processIdentifier} and {@link #processId} + * */ + public CreateCaseParamsBuilder process(Process process) { + this.process = process.clone(); + this.processIdentifier = process.getIdentifier(); + this.processId = process.getStringId(); + return this; + } + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/params/DeleteCaseParams.java b/src/main/java/com/netgrif/application/engine/workflow/domain/params/DeleteCaseParams.java new file mode 100644 index 00000000000..256cb2b8d2e --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/params/DeleteCaseParams.java @@ -0,0 +1,45 @@ +package com.netgrif.application.engine.workflow.domain.params; + +import com.netgrif.application.engine.workflow.domain.Case; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; + +@Data +@AllArgsConstructor +@Builder(builderMethodName = "with") +public class DeleteCaseParams { + + private String useCaseId; + private Case useCase; + private Boolean isTransactional; + @Builder.Default + private Map<String, String> params = new HashMap<>(); + + public DeleteCaseParams(Case useCase) { + this.useCase = useCase; + if (useCase != null) { + this.useCaseId = useCase.getStringId(); + } + } + + public DeleteCaseParams(String useCaseId) { + this.useCaseId = useCaseId; + } + + public static class DeleteCaseParamsBuilder { + /** + * Sets the {@link #useCase} and {@link #useCaseId} + * */ + public DeleteCaseParamsBuilder useCase(Case useCase) { + this.useCase = useCase; + if (useCase != null) { + this.useCaseId = useCase.getStringId(); + } + return this; + } + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/params/GetDataParams.java b/src/main/java/com/netgrif/application/engine/workflow/domain/params/GetDataParams.java new file mode 100644 index 00000000000..3a17f8e9ed4 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/params/GetDataParams.java @@ -0,0 +1,35 @@ +package com.netgrif.application.engine.workflow.domain.params; + +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.Task; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; + +@Data +@AllArgsConstructor +@Builder(builderMethodName = "with") +public class GetDataParams { + + private String taskId; + private Task task; + private String actorId; + private Case useCase; + private Boolean isTransactional; + @Builder.Default + private Map<String, String> params = new HashMap<>(); + + public GetDataParams(Task task, Case useCase, String actorId) { + this.task = task; + this.useCase = useCase; + this.actorId = actorId; + } + + public GetDataParams(String taskId, String actorId) { + this.taskId = taskId; + this.actorId = actorId; + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/params/SetDataParams.java b/src/main/java/com/netgrif/application/engine/workflow/domain/params/SetDataParams.java new file mode 100644 index 00000000000..e3bb75a45e7 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/params/SetDataParams.java @@ -0,0 +1,44 @@ +package com.netgrif.application.engine.workflow.domain.params; + +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.Task; +import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; + +@Data +@AllArgsConstructor +@Builder(builderMethodName = "with") +public class SetDataParams { + + private Task task; + private String taskId; + private Case useCase; + private DataSet dataSet; + private String actorId; + private Boolean isTransactional; + @Builder.Default + private Map<String, String> params = new HashMap<>(); + + public SetDataParams(Task task, DataSet dataSet, String actorId) { + this.task = task; + this.dataSet = dataSet; + this.actorId = actorId; + } + + public SetDataParams(String taskId, DataSet dataSet, String actorId) { + this.taskId = taskId; + this.dataSet = dataSet; + this.actorId = actorId; + } + + public SetDataParams(Case useCase, DataSet dataSet, String actorId) { + this.useCase = useCase; + this.dataSet = dataSet; + this.actorId = actorId; + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/params/TaskParams.java b/src/main/java/com/netgrif/application/engine/workflow/domain/params/TaskParams.java new file mode 100644 index 00000000000..533b059cc00 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/params/TaskParams.java @@ -0,0 +1,42 @@ +package com.netgrif.application.engine.workflow.domain.params; + +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.Task; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; + +@Data +@AllArgsConstructor +@Builder(builderMethodName = "with") +public class TaskParams { + + private String taskId; + private Task task; + private Case useCase; + private String assigneeId; + private Boolean isTransactional; + @Builder.Default + private Map<String, String> params = new HashMap<>(); + + public TaskParams(Task task) { + this.task = task; + } + + public TaskParams(Task task, String assigneeId) { + this.task = task; + this.assigneeId = assigneeId; + } + + public TaskParams(String taskId) { + this.taskId = taskId; + } + + public TaskParams(String taskId, String assigneeId) { + this.taskId = taskId; + this.assigneeId = assigneeId; + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/CaseRepositoryImpl.java b/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/CaseRepositoryImpl.java index ee0fb4cb847..c0769b34db8 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/CaseRepositoryImpl.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/CaseRepositoryImpl.java @@ -1,11 +1,10 @@ package com.netgrif.application.engine.workflow.domain.repositories; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference; import com.netgrif.application.engine.petrinet.web.responsebodies.Reference; import com.netgrif.application.engine.workflow.domain.QCase; -import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.core.types.dsl.StringExpression; import com.querydsl.core.types.dsl.StringPath; @@ -28,22 +27,22 @@ public abstract class CaseRepositoryImpl implements CaseRepository { @Override public void customize(QuerydslBindings bindings, QCase qCase) { - Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - List<PetriNetReference> nets = petriNetService.getReferencesByUsersProcessRoles(((LoggedUser) auth.getPrincipal()).getSelfOrImpersonated(), null); - Set<String> netIds = nets.stream().map(Reference::getStringId).collect(Collectors.toSet()); - Set<String> netIdentifiers = nets.stream().map(PetriNetReference::getIdentifier).collect(Collectors.toSet()); - - bindings.bind(qCase.petriNetId).first((stringPath, s) -> { - if (!netIds.contains(s)) - return Expressions.asBoolean(false); - return stringPath.equalsIgnoreCase(s); - }); - bindings.bind(qCase.processIdentifier).first((path, string) -> { - if (!netIdentifiers.contains(string)) - return Expressions.asBoolean(false); - return path.equalsIgnoreCase(string); - }); - bindings.bind(String.class).first((SingleValueBinding<StringPath, String>) StringExpression::equalsIgnoreCase); +// Authentication auth = SecurityContextHolder.getContext().getAuthentication(); +// List<PetriNetReference> nets = petriNetService.getReferencesByUsersRoles(((LoggedIdentity) auth.getPrincipal()).getSelfOrImpersonated(), null); +// Set<String> netIds = nets.stream().map(Reference::getStringId).collect(Collectors.toSet()); +// Set<String> netIdentifiers = nets.stream().map(PetriNetReference::getIdentifier).collect(Collectors.toSet()); +// +// bindings.bind(qCase.petriNetId).first((stringPath, s) -> { +// if (!netIds.contains(s)) +// return Expressions.asBoolean(false); +// return stringPath.equalsIgnoreCase(s); +// }); +// bindings.bind(qCase.processIdentifier).first((path, string) -> { +// if (!netIdentifiers.contains(string)) +// return Expressions.asBoolean(false); +// return path.equalsIgnoreCase(string); +// }); +// bindings.bind(String.class).first((SingleValueBinding<StringPath, String>) StringExpression::equalsIgnoreCase); // bindings.bind(qCase.dataSet).first((path, map) -> // map.entrySet().stream() // .map(o -> { @@ -53,6 +52,6 @@ public void customize(QuerydslBindings bindings, QCase qCase) { // return field.value.eq(o.getValue().getValue().toString()); // }) // .reduce(BooleanExpression::and).get()); - bindings.bind(qCase.title).first(StringExpression::likeIgnoreCase); +// bindings.bind(qCase.title).first(StringExpression::likeIgnoreCase); } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/TaskRepository.java b/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/TaskRepository.java index ade53dd9b05..c5a67a9cff1 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/TaskRepository.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/TaskRepository.java @@ -20,12 +20,14 @@ public interface TaskRepository extends MongoRepository<Task, String>, QuerydslP Page<Task> findByTransitionIdIn(Pageable pageable, Collection<String> ids); - Page<Task> findByUserId(Pageable pageable, String userId); + Page<Task> findByAssigneeId(Pageable pageable, String actorId); List<Task> findAllByTransitionIdInAndCaseId(Collection<String> transitionIds, String caseId); List<Task> findAllByIdIn(Iterable<String> id); + boolean existsByIdAndAssigneeId(String taskId, String actorId); + void deleteAllByProcessId(String processId); @Override diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/triggers/UserTrigger.java b/src/main/java/com/netgrif/application/engine/workflow/domain/triggers/ActorTrigger.java similarity index 76% rename from src/main/java/com/netgrif/application/engine/workflow/domain/triggers/UserTrigger.java rename to src/main/java/com/netgrif/application/engine/workflow/domain/triggers/ActorTrigger.java index da18785dd2e..a40cc68e847 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/domain/triggers/UserTrigger.java +++ b/src/main/java/com/netgrif/application/engine/workflow/domain/triggers/ActorTrigger.java @@ -4,22 +4,22 @@ import com.querydsl.core.annotations.PropertyType; import com.querydsl.core.annotations.QueryType; -import static com.netgrif.application.engine.importer.model.TriggerType.USER; +import static com.netgrif.application.engine.importer.model.TriggerType.ACTOR; -public class UserTrigger extends Trigger { +public class ActorTrigger extends Trigger { - public UserTrigger() { + public ActorTrigger() { super(); } @Override @QueryType(PropertyType.NONE) public TriggerType getType() { - return USER; + return ACTOR; } @Override public Trigger clone() { - return new UserTrigger(); + return new ActorTrigger(); } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java b/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java deleted file mode 100644 index 8e8991a3294..00000000000 --- a/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.netgrif.application.engine.workflow.service; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission; -import com.netgrif.application.engine.petrinet.domain.roles.RolePermission; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -public abstract class AbstractAuthorizationService { - - protected boolean hasPermission(Boolean hasPermission) { - return hasPermission != null && hasPermission; - } - - protected boolean hasRestrictedPermission(Boolean hasPermission) { - return hasPermission != null && !hasPermission; - } - - protected Map<ProcessRolePermission, Boolean> getAggregateProcessRolePermissions(IUser user, Map<String, Map<ProcessRolePermission, Boolean>> permissions) { - Map<ProcessRolePermission, Boolean> aggregatePermissions = new HashMap<>(); - - Set<String> userProcessRoleIDs = user.getSelfOrImpersonated().getProcessRoles().stream().map(role -> role.getId().toString()).collect(Collectors.toSet()); - - for (Map.Entry<String, Map<ProcessRolePermission, Boolean>> role : permissions.entrySet()) { - aggregateProcessRolePermission(userProcessRoleIDs, role, aggregatePermissions); - } - - return aggregatePermissions; - } - - private void aggregateProcessRolePermission(Set<String> userProcessRoleIDs, Map.Entry<String, Map<ProcessRolePermission, Boolean>> role, Map<ProcessRolePermission, Boolean> aggregatePermissions) { - if (!userProcessRoleIDs.contains(role.getKey())) { - return; - } - for (Map.Entry<ProcessRolePermission, Boolean> permission : role.getValue().entrySet()) { - Boolean permissionValue = permission.getValue(); - if (aggregatePermissions.containsKey(permission.getKey())) { - permissionValue = aggregatePermissions.get(permission.getKey()) && permissionValue; - } - aggregatePermissions.put(permission.getKey(), permissionValue); - } - } - - protected Map<RolePermission, Boolean> getAggregateRolePermissions(IUser user, Map<String, Map<RolePermission, Boolean>> permissions) { - Map<RolePermission, Boolean> aggregatePermissions = new HashMap<>(); - - Set<String> userProcessRoleIDs = user.getSelfOrImpersonated().getProcessRoles().stream().map(role -> role.getId().toString()).collect(Collectors.toSet()); - - for (Map.Entry<String, Map<RolePermission, Boolean>> role : permissions.entrySet()) { - aggregateRolePermission(userProcessRoleIDs, role, aggregatePermissions); - } - - return aggregatePermissions; - } - - private void aggregateRolePermission(Set<String> userProcessRoleIDs, Map.Entry<String, Map<RolePermission, Boolean>> role, Map<RolePermission, Boolean> aggregatePermissions) { - if (!userProcessRoleIDs.contains(role.getKey())) { - return; - } - for (Map.Entry<RolePermission, Boolean> permission : role.getValue().entrySet()) { - Boolean permissionValue = permission.getValue(); - if (aggregatePermissions.containsKey(permission.getKey())) { - permissionValue = aggregatePermissions.get(permission.getKey()) && permissionValue; - } - aggregatePermissions.put(permission.getKey(), permissionValue); - } - } -} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/UserFilterSearchService.java b/src/main/java/com/netgrif/application/engine/workflow/service/ActorFilterSearchService.java similarity index 81% rename from src/main/java/com/netgrif/application/engine/workflow/service/UserFilterSearchService.java rename to src/main/java/com/netgrif/application/engine/workflow/service/ActorFilterSearchService.java index ad133d28856..1495a2e65d4 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/UserFilterSearchService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/ActorFilterSearchService.java @@ -1,11 +1,11 @@ package com.netgrif.application.engine.workflow.service; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; import com.netgrif.application.engine.startup.FilterRunner; import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.service.interfaces.IUserFilterSearchService; +import com.netgrif.application.engine.workflow.service.interfaces.IActorFilterSearchService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.data.domain.Page; @@ -16,13 +16,13 @@ import java.util.List; @Service -public class UserFilterSearchService implements IUserFilterSearchService { +public class ActorFilterSearchService implements IActorFilterSearchService { @Autowired private IElasticCaseService caseSearchService; @Autowired - private IUserService userService; + private ISessionManagerService sessionManagerService; @Override public List<Case> autocompleteFindFilters(String userInput) { @@ -32,12 +32,12 @@ public List<Case> autocompleteFindFilters(String userInput) { .query( String.format("(title:%s*) AND ((dataSet.visibility.keyValue:private AND authorEmail:%s) OR (dataSet.visibility.keyValue:public))", userInput, - userService.getLoggedUser().getEmail()) + sessionManagerService.getLoggedIdentity().getUsername()) ) .transition(Collections.singletonList("view_filter")) .build() ), - this.userService.getLoggedOrSystem().transformToLoggedUser(), + sessionManagerService.getActiveActorId(), PageRequest.of(0, 100), LocaleContextHolder.getLocale(), true); diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/CaseEventHandler.java b/src/main/java/com/netgrif/application/engine/workflow/service/CaseEventHandler.java index b188442fa20..858a3b2b589 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/CaseEventHandler.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/CaseEventHandler.java @@ -2,26 +2,38 @@ import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.workflow.domain.Case; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.bson.Document; import org.bson.types.ObjectId; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; import org.springframework.data.mongodb.core.mapping.event.AfterDeleteEvent; +import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent; import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionalEventListener; @Slf4j @Component -public class CaseEventHandler extends AbstractMongoEventListener<Case> { +@RequiredArgsConstructor +public class CaseEventHandler { - @Autowired - private IElasticCaseService service; + private final IElasticCaseService service; - @Override + @TransactionalEventListener(fallbackExecution = true, condition = "#event.collectionName == 'case'") + public void onAfterSave(AfterSaveEvent<Case> event) { + Case useCase = event.getSource(); + try { + useCase.resolveImmediateDataFields(); + service.indexNow(useCase); + } catch (Exception e) { + log.error("Indexing failed [{}]", useCase.getStringId(), e); + } + } + + @TransactionalEventListener(fallbackExecution = true, condition = "#event.collectionName == 'case'") public void onAfterDelete(AfterDeleteEvent<Case> event) { Document document = event.getDocument(); - if (document == null) { - log.warn("Trying to delete null document!"); + if (document == null || document.isEmpty()) { + log.warn("Trying to delete null or empty document!"); return; } diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/ConfigurableMenuService.java b/src/main/java/com/netgrif/application/engine/workflow/service/ConfigurableMenuService.java index a92465c2963..2dcb31f241e 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/ConfigurableMenuService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/ConfigurableMenuService.java @@ -1,20 +1,9 @@ package com.netgrif.application.engine.workflow.service; -import com.netgrif.application.engine.auth.domain.Author; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField; import com.netgrif.application.engine.petrinet.domain.dataset.MultichoiceMapField; -import com.netgrif.application.engine.petrinet.domain.version.StringToVersionConverter; -import com.netgrif.application.engine.petrinet.domain.version.Version; -import com.netgrif.application.engine.petrinet.service.PetriNetService; -import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference; -import com.netgrif.application.engine.utils.FullPageRequest; import com.netgrif.application.engine.workflow.service.interfaces.IConfigurableMenuService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; @@ -22,72 +11,7 @@ @Service public class ConfigurableMenuService implements IConfigurableMenuService { - - @Autowired - private PetriNetService petriNetService; - @Autowired - private StringToVersionConverter converter; - - /** - * Constructs a map that can be used as a value for any {@link com.netgrif.application.engine.petrinet.domain.dataset.MapOptionsField}. - * <p> - * The map will contain strings related to process nets authored by the provided user. - * <p> - * A key of the map is a string of the form "<net identifier>:<net version>". - * The version portion of the string uses the dash (-) character to separate the major, minor a patch version numbers instead of the traditional dot character. - * <p> - * A value of the map is an {@link I18nString} with no translations of the form "<net identifier> : <net version>". - * The default value of the net title is used. - * - * @param author currently logged user - * @return an options map containing the identifiers and version of nets authored by the provided user as keys and their titles and versions as values - */ - @Override - public Map<String, I18nString> getNetsByAuthorAsMapOptions(IUser author, Locale locale) { - LoggedUser loggedAuthor = author.transformToLoggedUser(); - PetriNetSearch requestQuery = new PetriNetSearch(); - Author authorQuery = new Author(); - authorQuery.setEmail(author.getEmail()); - requestQuery.setAuthor(authorQuery); - List<PetriNetReference> nets = this.petriNetService.search(requestQuery, loggedAuthor, new FullPageRequest(), locale).getContent(); - - Map<String, I18nString> options = new HashMap<>(); - - for (PetriNetReference net : nets) { - String[] versionSplit = net.getVersion().split("\\."); - I18nString titleAndVersion = new I18nString(net.getTitle() + " :" + net.getVersion()); - options.put(net.getIdentifier() + ":" + versionSplit[0] + "-" + versionSplit[1] + "-" + versionSplit[2], titleAndVersion); - } - - return options; - } - - /** - * Constructs a map that can be used as a value for any {@link com.netgrif.application.engine.petrinet.domain.dataset.MapOptionsField}. - * <p> - * The map will contain roles from the net selected in the provided field, that are not present in either of the provided multichoice fields. - * <p> - * A key of the map is a string of the form "<role identifier>:<net identifier>" - * <p> - * A value of the map is the role title. - * - * @param processField the value of the field determines the process whose roles are put into the result. - * The options key must match the format generated by the {@link ConfigurableMenuService#getNetsByAuthorAsMapOptions(IUser, Locale)} method - * @param permittedRoles the roles selected in this multichoice will not be present in the result. The option keys of this multichoice must match the format returned by this method - * @param bannedRoles the roles selected in this multichoice will not be present in the result. The option keys of this multichoice must match the format returned by this method - * @return an options map containing the role and net identifiers as keys and the role titles as values - */ - @Override - public Map<String, I18nString> getAvailableRolesFromNet(EnumerationMapField processField, MultichoiceMapField permittedRoles, MultichoiceMapField bannedRoles) { - String netImportId = processField.getValue().getValue().split(":")[0]; - String versionString = processField.getValue().getValue().split(":")[1].replace("-", "."); - Version version = converter.convert(versionString); - PetriNet net = petriNetService.getPetriNet(netImportId, version); - return net.getRoles().values().stream() - .filter(role -> (!permittedRoles.getOptions().containsKey(role.getImportId() + ":" + netImportId) - && !bannedRoles.getOptions().containsKey(role.getImportId() + ":" + netImportId))) - .collect(Collectors.toMap(o -> o.getImportId() + ":" + netImportId, v -> v.getName().clone())); - } + // todo: release/8.0.0 menu items /** * Constructs a map that can be used as a value for any {@link com.netgrif.application.engine.petrinet.domain.dataset.MapOptionsField}. @@ -115,8 +39,8 @@ public Map<String, I18nString> removeSelectedRoles(MultichoiceMapField mapField) * and new values corresponding to the new keys from the {@code rolesAvailable} field. The new values are of the form "<original value> (<net title>)" * * @param addedRoles a field containing the preexisting options. The options of this field are assumed to be generated by this method. - * @param processField a field containing the information about the selected process. The options of this field are assumed to be generated by the {@link ConfigurableMenuService#getNetsByAuthorAsMapOptions(IUser, Locale)} method - * @param rolesAvailable a field containing the selection of the new roles. The options of this field are assumed to be generated by the {@link ConfigurableMenuService#getAvailableRolesFromNet(EnumerationMapField, MultichoiceMapField, MultichoiceMapField)} method + * @param processField a field containing the information about the selected process. + * @param rolesAvailable a field containing the selection of the new roles. * @return a map containing a quasi-union of the options from the {@code addedRoles} and {@code rolesAvailable} fields */ @Override diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/CrudSystemCaseService.java b/src/main/java/com/netgrif/application/engine/workflow/service/CrudSystemCaseService.java new file mode 100644 index 00000000000..e6e945e6712 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/service/CrudSystemCaseService.java @@ -0,0 +1,392 @@ +package com.netgrif.application.engine.workflow.service; + +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseSearchService; +import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.transaction.NaeTransaction; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.CaseParams; +import com.netgrif.application.engine.workflow.domain.QCase; +import com.netgrif.application.engine.workflow.domain.SystemCase; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.service.interfaces.ICrudSystemCaseService; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import com.netgrif.application.engine.workflow.service.throwable.CaseAlreadyExistsException; +import groovy.lang.Closure; +import lombok.extern.slf4j.Slf4j; +import org.bson.types.ObjectId; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.mongodb.MongoTransactionManager; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +import javax.validation.constraints.NotNull; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +@Slf4j +public abstract class CrudSystemCaseService<T extends SystemCase> implements ICrudSystemCaseService<T> { + + protected final ISessionManagerService sessionManagerService; + protected final IDataService dataService; + protected final IWorkflowService workflowService; + protected final SystemCaseFactoryRegistry systemCaseFactory; + protected final IElasticCaseSearchService elasticCaseSearchService; + protected final MongoTransactionManager transactionManager; + /** + * todo javadoc + * */ + protected final Set<String> forbiddenKeywords; + + protected CrudSystemCaseService(ISessionManagerService sessionManagerService, IDataService dataService, + IWorkflowService workflowService, SystemCaseFactoryRegistry systemCaseFactory, + IElasticCaseSearchService elasticCaseSearchService, MongoTransactionManager transactionManager) { + this.sessionManagerService = sessionManagerService; + this.dataService = dataService; + this.workflowService = workflowService; + this.systemCaseFactory = systemCaseFactory; + this.elasticCaseSearchService = elasticCaseSearchService; + this.transactionManager = transactionManager; + this.forbiddenKeywords = ConcurrentHashMap.newKeySet(); + } + + /** + * Returns the unique process identifier for this system case service. + * + * @return Process identifier string + */ + protected abstract String getProcessIdentifier(); + + /** + * Generates a search query to find existing cases with the same unique properties. + * + * @param params Parameters containing the unique properties to search for + * @return Search query string + */ + protected abstract String isUniqueQuery(@NotNull CaseParams params); + + /** + * Validates and fixes parameters for case creation. + * + * @param params Parameters to validate + * @throws IllegalArgumentException if parameters are invalid + */ + protected abstract void validateAndFixCreateParams(@NotNull CaseParams params) throws IllegalArgumentException; + + /** + * Validates and fixes parameters for case update. + * + * @param params Parameters to validate + * @throws IllegalArgumentException if parameters are invalid + */ + protected abstract void validateAndFixUpdateParams(@NotNull CaseParams params) throws IllegalArgumentException; + + /** + * Performs any necessary actions after system case creation. + * + * @param systemCase The newly created system case + */ + protected void postCreationActions(T systemCase) {} + + /** + * Performs any necessary actions after system case update. + * + * @param systemCase The updated system case + */ + protected void postUpdateActions(T systemCase) {} + + /** + * todo javadoc + * */ + @Override + public boolean registerForbiddenKeywords(Set<String> keywords) { + // todo: release/8.0.0 authorisation + if (keywords == null) { + return false; + } + boolean areRegistered = this.forbiddenKeywords.addAll(keywords); + if (areRegistered) { + log.debug("New forbidden keywords for process [{}] were registered: {}", getProcessIdentifier(), keywords); + } + return areRegistered; + } + + /** + * todo javadoc + * */ + @Override + public boolean removeForbiddenKeywords(Set<String> keywords) { + // todo: release/8.0.0 authorisation + if (keywords == null) { + return false; + } + boolean areRemoved = this.forbiddenKeywords.removeAll(keywords); + if (areRemoved) { + log.debug("Some forbidden keywords for process [{}] were removed: {}", getProcessIdentifier(), keywords); + } + return areRemoved; + } + + @Override + public void clearForbiddenKeywords() { + int countBefore = this.forbiddenKeywords.size(); + this.forbiddenKeywords.clear(); + if (countBefore > 0) { + log.debug("All ({}) forbidden keywords for process [{}] were removed", countBefore, getProcessIdentifier()); + } + } + + /** + * todo javadoc + * Creates identity based on params. Password is not encoded. User is not created. + * + * @param params Parameters, that are used to create the identity. At least username must be provided. + * + * @return Created identity. Cannot be null + * + * @throws IllegalArgumentException if the input parameters are invalid + * */ + @Override + @SuppressWarnings("unchecked") + public T create(CaseParams params) throws IllegalArgumentException, IllegalStateException, CaseAlreadyExistsException { + if (params == null) { + throw new IllegalArgumentException("Please provide input parameters."); + } + if (!params.targetProcessIdentifier().equals(getProcessIdentifier())) { + throw new IllegalArgumentException("Wrong type of parameters was provided."); + } + validateAndFixCreateParams(params); + + Optional<T> existingCaseOpt = findOneByQuery(isUniqueQuery(params)); + if (existingCaseOpt.isPresent()) { + throw new CaseAlreadyExistsException(String.format("Such instance with id [%s] of process [%s] already exists.", + existingCaseOpt.get().getStringId(), getProcessIdentifier())); + } + + final String activeActorId = sessionManagerService.getActiveActorId(); + + T systemObject; + if (!TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<T>(null) { + @Override + public T call() { + return doCreate(params, activeActorId); + } + }) + .build(); + transaction.begin(); + systemObject = (T) transaction.getResultOfEvent(); + } else { + systemObject = doCreate(params, activeActorId); + } + + postCreationActions(systemObject); + return systemObject; + } + + @SuppressWarnings("unchecked") + protected T doCreate(CaseParams params, String activeActorId) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(getProcessIdentifier()) + .authorId(activeActorId) + .build(); + Case systemCase = workflowService.createCase(createCaseParams).getCase(); + systemCase = dataService.setData(new SetDataParams(systemCase, params.toDataSet(), + activeActorId)).getCase(); + if (params.getProperties() != null) { + systemCase.setProperties(params.getProperties()); + systemCase = workflowService.save(systemCase); + } + T systemObject = (T) systemCaseFactory.fromCase(systemCase); + + if (systemObject == null) { + throw new IllegalStateException(String.format("Unexpected: No wrapper class factory is registered for process [%s]", + getProcessIdentifier())); + } + log.debug("System case [{}][{}] was created by actor [{}].", systemObject.getCase(), getProcessIdentifier(), + activeActorId); + return systemObject; + } + + @Override + @SuppressWarnings("unchecked") + public T update(T systemObject, CaseParams params) throws IllegalArgumentException, IllegalStateException { + if (systemObject == null) { + throw new IllegalArgumentException("Please provide case to be updated"); + } + if (params == null) { + throw new IllegalArgumentException("Please provide input parameters."); + } + if (!params.targetProcessIdentifier().equals(getProcessIdentifier())) { + throw new IllegalArgumentException("Wrong type of parameters was provided."); + } + + validateAndFixUpdateParams(params); + + final String activeActorId = sessionManagerService.getActiveActorId(); + + if (!TransactionSynchronizationManager.isSynchronizationActive()) { + T finalSystemObject = systemObject; + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<T>(null) { + @Override + public T call() { + return doUpdate(finalSystemObject, params, activeActorId); + } + }) + .build(); + transaction.begin(); + systemObject = (T) transaction.getResultOfEvent(); + } else { + systemObject = doUpdate(systemObject, params, activeActorId); + } + + postUpdateActions(systemObject); + + return systemObject; + } + + @SuppressWarnings("unchecked") + protected T doUpdate(SystemCase systemObject, CaseParams params, String activeActorId) { + Case systemCase = dataService.setData(new SetDataParams(systemObject.getCase(), params.toDataSet(), + activeActorId)).getCase(); + + if (params.getProperties() != null) { + systemCase.setProperties(params.getProperties()); + systemCase = workflowService.save(systemCase); + } + + systemObject = systemCaseFactory.fromCase(systemCase); + + if (systemObject == null) { + throw new IllegalStateException(String.format("Unexpected: No wrapper class factory is registered for process [%s]", + getProcessIdentifier())); + } + log.debug("System case [{}][{}] was updated by actor [{}].", systemObject, getProcessIdentifier(), activeActorId); + return (T) systemObject; + } + + /** + * todo javadoc + * Finds identity by id. + * + * @param id id of the identity. If provided null, empty optional is returned + * + * @return If the identity exists, it's returned. If not, an empty optional is returned + */ + @Override + @SuppressWarnings("unchecked") + public Optional<T> findById(String id) { + if (id == null) { + return Optional.empty(); + } + try { + final Case systemCase = workflowService.findOne(id); + if (!systemCase.getProcessIdentifier().equals(getProcessIdentifier())) { + return Optional.empty(); + } + return (Optional<T>) Optional.ofNullable(systemCaseFactory.fromCase(systemCase)); + } catch (IllegalArgumentException ignored) { + return Optional.empty(); + } + } + + @Override + public boolean existsById(String id) { + if (id == null) { + return false; + } + // todo: release/8.0.0 edge case: can return true and findById will return empty optional + return workflowService.count(QCase.case$.processIdentifier.eq(getProcessIdentifier()) + .and(QCase.case$.id.eq(new ObjectId(id)))) > 0; + } + + @Override + @SuppressWarnings("unchecked") + public List<T> findAll() { + List<Case> result = workflowService.searchAll(QCase.case$.processIdentifier.eq(getProcessIdentifier())).getContent(); + return (List<T>) result.stream() + .map(systemCaseFactory::fromCase) + .collect(Collectors.toList()); + } + + // todo: release/8.0.0 also removal method? + + protected boolean isForbidden(String keyword) { + return this.forbiddenKeywords.contains(keyword); + } + + protected boolean isTextFieldOrValueEmpty(TextField field) { + return field == null || isTextFieldValueEmpty(field); + } + + protected boolean isTextFieldValueEmpty(TextField field) { + return field.getRawValue() == null || field.getRawValue().trim().isEmpty(); + } + + protected boolean isCaseFieldOrValueEmpty(CaseField field) { + return field == null || isCaseFieldValueEmpty(field); + } + + protected boolean isCaseFieldValueEmpty(CaseField field) { + return field.getRawValue() == null || field.getRawValue().isEmpty(); + } + + protected List<? extends Case> findAllByQuery(String query) { + Set<String> singletonQuerySet = query != null ? Set.of(query) : Set.of(); + CaseSearchRequest request = CaseSearchRequest.builder() + .query(buildQuery(singletonQuerySet)) + .build(); + + Page<Case> pageResult = elasticCaseSearchService.search(List.of(request), sessionManagerService.getActiveActorId(), + Pageable.unpaged(), Locale.getDefault(), false, null); + + return pageResult.getContent(); + } + + @SuppressWarnings("unchecked") + protected Optional<T> findOneByQuery(String query) { + if (query == null) { + return Optional.empty(); + } + CaseSearchRequest request = CaseSearchRequest.builder() + .query(buildQuery(Set.of(query))) + .build(); + Page<Case> resultAsPage = elasticCaseSearchService.search(List.of(request), sessionManagerService.getActiveActorId(), + PageRequest.of(0, 1), Locale.getDefault(), false, null); + if (resultAsPage.hasContent()) { + return (Optional<T>) Optional.ofNullable(systemCaseFactory.fromCase(resultAsPage.getContent().get(0))); + } + return Optional.empty(); + } + + protected long countByQuery(String query) { + CaseSearchRequest request = CaseSearchRequest.builder() + .query(buildQuery(Set.of(query))) + .build(); + return elasticCaseSearchService.count(List.of(request), sessionManagerService.getActiveActorId(), + Locale.getDefault(), false, null); + } + + protected String buildQuery(Set<String> andQueries) { + StringBuilder queryBuilder = new StringBuilder("processIdentifier:").append(getProcessIdentifier()); + for (String query : andQueries) { + queryBuilder.append(" AND "); + queryBuilder.append(query); + } + return queryBuilder.toString(); + } + + protected static String fulltextFieldQuery(String fieldId, String fieldValue) { + return String.format("dataSet.%s.fulltextValue:\"%s\"", fieldId, fieldValue); + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/DataService.java b/src/main/java/com/netgrif/application/engine/workflow/service/DataService.java index fe5e93bf263..777e00b1d48 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/DataService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/DataService.java @@ -1,15 +1,12 @@ package com.netgrif.application.engine.workflow.service; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.authorization.domain.User; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; import com.netgrif.application.engine.history.domain.dataevents.GetDataEventLog; import com.netgrif.application.engine.history.domain.dataevents.SetDataEventLog; import com.netgrif.application.engine.history.service.IHistoryService; import com.netgrif.application.engine.importer.model.DataEventType; import com.netgrif.application.engine.importer.model.DataType; -import com.netgrif.application.engine.importer.model.LayoutType; -import com.netgrif.application.engine.importer.service.FieldFactory; import com.netgrif.application.engine.petrinet.domain.Component; import com.netgrif.application.engine.petrinet.domain.*; import com.netgrif.application.engine.petrinet.domain.dataset.*; @@ -17,22 +14,26 @@ import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionRunner; import com.netgrif.application.engine.petrinet.domain.events.DataEvent; import com.netgrif.application.engine.petrinet.domain.events.EventPhase; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.validation.service.interfaces.IValidationService; -import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.DataFieldBehavior; -import com.netgrif.application.engine.workflow.domain.EventNotExecutableException; -import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.GetDataEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.GetDataGroupsEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.TaskEventOutcome; +import com.netgrif.application.engine.petrinet.domain.layout.LayoutContainer; +import com.netgrif.application.engine.petrinet.domain.layout.LayoutItem; +import com.netgrif.application.engine.petrinet.domain.layout.LayoutObjectType; +import com.netgrif.application.engine.transaction.NaeTransaction; +import com.netgrif.application.engine.transaction.configuration.NaeTransactionProperties; +import com.netgrif.application.engine.validations.interfaces.IValidationService; +import com.netgrif.application.engine.workflow.domain.*; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.GetDataEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.layoutoutcomes.GetLayoutsEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.TaskEventOutcome; +import com.netgrif.application.engine.workflow.domain.params.GetDataParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; import com.netgrif.application.engine.workflow.service.interfaces.IDataService; import com.netgrif.application.engine.workflow.service.interfaces.IEventService; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; +import groovy.lang.Closure; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.pdfbox.pdmodel.PDDocument; @@ -41,9 +42,10 @@ import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; +import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; @@ -60,63 +62,78 @@ public class DataService implements IDataService { @Autowired - protected ApplicationEventPublisher publisher; + private ITaskService taskService; @Autowired - protected ITaskService taskService; + private IWorkflowService workflowService; @Autowired - protected IWorkflowService workflowService; + private ActionRunner actionsRunner; @Autowired - protected IUserService userService; + private IEventService eventService; @Autowired - protected FieldFactory fieldFactory; + private IHistoryService historyService; @Autowired - protected ActionRunner actionsRunner; + private MongoTransactionManager transactionManager; @Autowired - protected IEventService eventService; + private IValidationService validationService; @Autowired - protected IHistoryService historyService; + private NaeTransactionProperties transactionProperties; @Autowired - protected IPetriNetService petriNetService; - - @Autowired - protected IValidationService validation; + private IUserService userService; @Value("${nae.image.preview.scaling.px:400}") - protected int imageScale; - - @Value("${nae.validation.setData.enable:false}") - protected boolean validationEnable; - - @Override - public GetDataEventOutcome getData(String taskId, IUser user) { - return getData(taskId, user, new HashMap<>()); - } + private int imageScale; + + /** + * Gets the data of the {@link Task} provided by {@link GetDataParams} + * + * @param getDataParams parameters where the Task is specified + * <br> + * <b>Required parameters</b> + * <ul> + * <li>taskId or task</li> + * <li>user</li> + * </ul> + * + * @return outcome containing the fields present in Task + * */ + @Override + public GetDataEventOutcome getData(GetDataParams getDataParams) { + fillMissingAttributes(getDataParams); + + Case useCase = getDataParams.getUseCase(); + Task task = getDataParams.getTask(); - @Override - public GetDataEventOutcome getData(String taskId, IUser user, Map<String, String> params) { - Task task = taskService.findOne(taskId); - Case useCase = workflowService.findOne(task.getCaseId()); - - return getData(task, useCase, user, params); - } + log.info("[{}]: Getting data of task {} [{}]", useCase.getStringId(), task.getTransitionId(), task.getStringId()); - @Override - public GetDataEventOutcome getData(Task task, Case useCase, IUser user) { - return getData(task, useCase, user, new HashMap<>()); + if (getDataParams.getIsTransactional() && !TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<GetDataEventOutcome>(null) { + @Override + public GetDataEventOutcome call() { + return doGetData(getDataParams); + } + }) + .build(); + transaction.begin(); + return (GetDataEventOutcome) transaction.getResultOfEvent(); + } else { + return doGetData(getDataParams); + } } - @Override - public GetDataEventOutcome getData(Task task, Case useCase, IUser user, Map<String, String> params) { - log.info("[{}]: Getting data of task {} [{}]", useCase.getStringId(), task.getTransitionId(), task.getStringId()); - Transition transition = useCase.getPetriNet().getTransition(task.getTransitionId()); + private GetDataEventOutcome doGetData(GetDataParams getDataParams) { + Case useCase = getDataParams.getUseCase(); + Task task = getDataParams.getTask(); + Transition transition = useCase.getProcess().getTransition(task.getTransitionId()); Map<String, DataRef> dataRefs = transition.getDataSet(); List<DataRef> dataSetFields = new ArrayList<>(); GetDataEventOutcome outcome = new GetDataEventOutcome(useCase, task); @@ -128,8 +145,10 @@ public GetDataEventOutcome getData(Task task, Case useCase, IUser user, Map<Stri if (behavior.isForbidden()) { return; } - outcome.addOutcomes(resolveDataEvents(field, DataEventType.GET, EventPhase.PRE, useCase, task, null, params)); - historyService.save(new GetDataEventLog(task, useCase, EventPhase.PRE, user)); + outcome.addOutcomes(resolveDataEvents(field, DataEventType.GET, EventPhase.PRE, useCase, task, null, + getDataParams.getParams())); + + historyService.save(new GetDataEventLog(task, useCase, EventPhase.PRE, getDataParams.getActorId())); if (outcome.getMessage() == null) { setOutcomeMessage(task, useCase, outcome, fieldId, field, DataEventType.GET); @@ -139,8 +158,10 @@ public GetDataEventOutcome getData(Task task, Case useCase, IUser user, Map<Stri dataRef.setBehavior(behavior); dataSetFields.add(dataRef); // TODO: release/8.0.0 params into outcome? - outcome.addOutcomes(resolveDataEvents(field, DataEventType.GET, EventPhase.POST, useCase, task, null, params)); - historyService.save(new GetDataEventLog(task, useCase, EventPhase.POST, user)); + outcome.addOutcomes(resolveDataEvents(field, DataEventType.GET, EventPhase.POST, useCase, task, null, + getDataParams.getParams())); + + historyService.save(new GetDataEventLog(task, useCase, EventPhase.POST, getDataParams.getActorId())); }); workflowService.save(useCase); @@ -148,103 +169,146 @@ public GetDataEventOutcome getData(Task task, Case useCase, IUser user, Map<Stri return outcome; } - @Override - public SetDataEventOutcome setData(String taskId, DataSet dataSet, IUser user) { - return setData(taskId, dataSet, user, new HashMap<>()); - } - - @Override - public SetDataEventOutcome setData(String taskId, DataSet dataSet, IUser user, Map<String, String> params) { - Task task = taskService.findOne(taskId); - return setData(task, dataSet, user, params); - } - - @Override - public SetDataEventOutcome setData(String taskId, DataSet values, LoggedUser loggedUser) { - return setData(taskId, values, loggedUser, new HashMap<>()); - } - - @Override - public SetDataEventOutcome setData(String taskId, DataSet dataSet, LoggedUser loggedUser, Map<String, String> params) { - IUser user = userService.getUserFromLoggedUser(loggedUser); - return setData(taskId, dataSet, user, params); - } - - @Override - public SetDataEventOutcome setData(Case target, DataSet dataSet, IUser user) { - return setData(target, dataSet, user, new HashMap<>()); - } - - @Override - public SetDataEventOutcome setData(Case target, DataSet dataSet, IUser user, Map<String, String> params) { - Task fake = Task.with().id(new ObjectId()).caseId(target.getStringId()).title(new I18nString("Fake")).transitionId("fake").build(); - return setData(fake, dataSet, user, params); + private void fillMissingAttributes(GetDataParams getDataParams) throws IllegalArgumentException { + if (getDataParams.getActorId() == null) { + throw new IllegalArgumentException("Actor must be provided on get data."); + } + if (getDataParams.getTask() == null) { + Task task = taskService.findOne(getDataParams.getTaskId()); + getDataParams.setTask(task); + } + if (getDataParams.getUseCase() == null) { + Case useCase = workflowService.findOne(getDataParams.getTask().getCaseId()); + getDataParams.setUseCase(useCase); + } + if (getDataParams.getIsTransactional() == null) { + getDataParams.setIsTransactional(transactionProperties.isGetDataTransactional()); + } } - @Override - public SetDataEventOutcome setData(Task task, DataSet dataSet, IUser user) { - return setData(task, dataSet, user, new HashMap<>()); + /** + * Sets the provided data by {@link SetDataParams} + * + * @param setDataParams parameters containing the data to be set within the {@link Case} or {@link Task} object + * <br> + * <b>Required parameters</b> + * <ul> + * <li>taskId or task or useCase</li> + * <li>user</li> + * </ul> + * + * @return outcome containing changed fields, updated Task and Case + * */ + @Override + public SetDataEventOutcome setData(SetDataParams setDataParams) { + fillMissingAttributes(setDataParams); + + Task task = setDataParams.getTask(); + + log.info("[{}]: Setting data of task {} [{}] by actor [{}]", task.getStringId(), task.getTransitionId(), + task.getStringId(), setDataParams.getActorId()); + + if (setDataParams.getIsTransactional() && !TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<SetDataEventOutcome>(null) { + @Override + public SetDataEventOutcome call() { + return doSetData(setDataParams); + } + }) + .build(); + transaction.begin(); + return (SetDataEventOutcome) transaction.getResultOfEvent(); + } else { + return doSetData(setDataParams); + } } - @Override - public SetDataEventOutcome setData(Task task, DataSet dataSet, IUser user, Map<String, String> params) { - log.info("[{}]: Setting data of task {} [{}]", task.getStringId(), task.getTransitionId(), task.getStringId()); - if (task.getUserId() != null) { - task.setUser(userService.findById(task.getUserId())); - } + private SetDataEventOutcome doSetData(SetDataParams setDataParams) { + Task task = setDataParams.getTask(); List<EventOutcome> outcomes = new ArrayList<>(); - for (Map.Entry<String, Field<?>> stringFieldEntry : dataSet.getFields().entrySet()) { + for (Map.Entry<String, Field<?>> stringFieldEntry : setDataParams.getDataSet().getFields().entrySet()) { String fieldId = stringFieldEntry.getKey(); Field<?> newDataField = stringFieldEntry.getValue(); - outcomes.add(setDataField(task, fieldId, newDataField, user)); + SetDataEventOutcome setDataEventOutcome = setDataField(task, fieldId, newDataField, setDataParams.getActorId()); + outcomes.add(setDataEventOutcome); } Case useCase = workflowService.findOne(task.getCaseId()); return new SetDataEventOutcome(useCase, task, outcomes); } + private void fillMissingAttributes(SetDataParams setDataParams) { + if (setDataParams.getTask() == null) { + if (setDataParams.getTaskId() != null) { + Task task = taskService.findOne(setDataParams.getTaskId()); + setDataParams.setTask(task); + } else if (setDataParams.getUseCase() != null) { + Task fakeTask = Task.with() + .id(new ObjectId()) + .caseId(setDataParams.getUseCase().getStringId()) + .title(new I18nString("Fake")) + .transitionId("fake") + .build(); + setDataParams.setTask(fakeTask); + } else { + throw new IllegalArgumentException("Cannot set data without provided task."); + } + } + if (setDataParams.getIsTransactional() == null) { + setDataParams.setIsTransactional(transactionProperties.isSetDataTransactional()); + } + } + @Override - public SetDataEventOutcome setDataField(Task task, String fieldId, Field<?> newDataField, IUser user) { - return setDataField(task, fieldId, newDataField, user, new HashMap<>()); + public SetDataEventOutcome setDataField(Task task, String fieldId, Field<?> newDataField, String actorId) { + return setDataField(task, fieldId, newDataField, actorId, new HashMap<>()); } // TODO: release/8.0.0 check @Override - public SetDataEventOutcome setDataField(Task task, String fieldId, Field<?> newDataField, IUser user, Map<String, String> params) { - // TODO: NAE-1859 permissions? + public SetDataEventOutcome setDataField(Task task, String fieldId, Field<?> newDataField, String actorId, Map<String, String> params) { + // TODO: release/8.0.0 permissions? Case useCase = workflowService.findOne(task.getCaseId()); SetDataEventOutcome outcome = new SetDataEventOutcome(useCase, task); - Optional<Field<?>> fieldOptional = useCase.getPetriNet().getField(fieldId); + Optional<Field<?>> fieldOptional = useCase.getProcess().getField(fieldId); if (fieldOptional.isEmpty()) { - throw new IllegalArgumentException("[" + useCase.getStringId() + "] Field " + fieldId + " does not exist in case " + useCase.getTitle() + " of process " + useCase.getPetriNet().getStringId()); + throw new IllegalArgumentException("[" + useCase.getStringId() + "] Field " + fieldId + " does not exist in case " + useCase.getTitle() + " of process " + useCase.getProcess().getStringId()); } Field<?> field = fieldOptional.get(); // PRE - outcome.addOutcomes(resolveDataEvents(field, DataEventType.SET, EventPhase.PRE, useCase, task, newDataField, params)); - useCase = workflowService.findOne(task.getCaseId()); - historyService.save(new SetDataEventLog(task, useCase, EventPhase.PRE, DataSet.of(fieldId, newDataField), user)); + List<EventOutcome> preSetOutcomes = resolveDataEvents(field, DataEventType.SET, EventPhase.PRE, useCase, task, newDataField, params); + if (!preSetOutcomes.isEmpty()) { + outcome.addOutcomes(preSetOutcomes); + useCase = workflowService.findOne(task.getCaseId()); + } + historyService.save(new SetDataEventLog(task, useCase, EventPhase.PRE, DataSet.of(fieldId, newDataField), actorId)); + // EXECUTION if (outcome.getMessage() == null) { setOutcomeMessage(task, useCase, outcome, fieldId, field, DataEventType.SET); } useCase.getDataSet().get(fieldId).applyChanges(newDataField); - if (validationEnable) { - validation.valid(useCase.getDataSet().get(fieldId)); - } + validationService.validateField(useCase, useCase.getDataSet().get(fieldId)); + useCase = workflowService.save(useCase); outcome.addChangedField(fieldId, newDataField); - historyService.save(new SetDataEventLog(task, useCase, EventPhase.EXECUTION, DataSet.of(fieldId, newDataField), user)); + historyService.save(new SetDataEventLog(task, useCase, EventPhase.EXECUTION, DataSet.of(fieldId, newDataField), actorId)); // POST - outcome.addOutcomes(resolveDataEvents(field, DataEventType.SET, EventPhase.POST, useCase, task, newDataField, params)); - useCase = workflowService.findOne(task.getCaseId()); - historyService.save(new SetDataEventLog(task, useCase, EventPhase.POST, DataSet.of(fieldId, newDataField), user)); - useCase = applyFieldConnectedChanges(useCase, field); + List<EventOutcome> postSetOutcomes = resolveDataEvents(field, DataEventType.SET, EventPhase.POST, useCase, task, newDataField, params); + if (!postSetOutcomes.isEmpty()) { + outcome.addOutcomes(postSetOutcomes); + useCase = workflowService.findOne(task.getCaseId()); + } + historyService.save(new SetDataEventLog(task, useCase, EventPhase.POST, DataSet.of(fieldId, newDataField), actorId)); + outcome.setCase(useCase); return outcome; } private void setOutcomeMessage(Task task, Case useCase, TaskEventOutcome outcome, String fieldId, Field<?> field, DataEventType type) { - Map<String, DataRef> caseDataSet = useCase.getPetriNet().getTransition(task.getTransitionId()).getDataSet(); + Map<String, DataRef> caseDataSet = useCase.getProcess().getTransition(task.getTransitionId()).getDataSet(); I18nString message = null; if (field.getEvents().containsKey(type)) { message = field.getEvents().get(type).getMessage(); @@ -255,71 +319,78 @@ private void setOutcomeMessage(Task task, Case useCase, TaskEventOutcome outcome } @Override - public GetDataGroupsEventOutcome getDataGroups(String taskId, Locale locale, LoggedUser loggedUser) { - IUser user = userService.getUserFromLoggedUser(loggedUser); - return getDataGroups(taskId, locale, user); - } + public GetLayoutsEventOutcome getLayouts(String taskId, Locale locale, String actorId) { + Task task = taskService.findOne(taskId); + Case useCase = workflowService.findOne(task.getCaseId()); - @Override - public GetDataGroupsEventOutcome getDataGroups(String taskId, Locale locale, IUser user) { - return getDataGroups(taskId, locale, new HashSet<>(), 0, null, user); + GetLayoutsEventOutcome outcome = new GetLayoutsEventOutcome(useCase, task); + LayoutContainer originContainer = useCase.getProcess().getTransition(task.getTransitionId()).getLayoutContainer(); + if (originContainer == null) { + return outcome; + } + + outcome.setLayout( + this.processLayoutContainer(originContainer.clone(), task, useCase, actorId, outcome, locale, + false, new LinkedHashSet<>()) + ); + return outcome; } - private GetDataGroupsEventOutcome getDataGroups(String taskId, Locale locale, Set<String> collectedTaskIds, int level, String parentTaskRefId, IUser user) { - Task task = taskService.findOne(taskId); - Case useCase = workflowService.findOne(task.getCaseId()); - PetriNet net = useCase.getPetriNet(); - Transition transition = net.getTransition(task.getTransitionId()); - GetDataGroupsEventOutcome outcome = new GetDataGroupsEventOutcome(useCase, task); - log.info("Getting groups of task " + taskId + " in case " + useCase.getTitle() + " level: " + level); - List<DataGroup> resultDataGroups = new ArrayList<>(); - List<DataRef> data = getData(task, useCase, user).getData(); - Map<String, DataRef> dataFieldMap = data.stream().collect(Collectors.toMap(DataRef::getFieldId, field -> field)); - List<DataGroup> dataGroups = transition.getDataGroups().values().stream().map(DataGroup::clone).collect(Collectors.toList()); - for (DataGroup dataGroup : dataGroups) { - resolveTaskRefOrderOnGrid(dataGroup, dataFieldMap); - resultDataGroups.add(dataGroup); - log.debug("Setting groups of task " + taskId + " in case " + useCase.getTitle() + " level: " + level + " " + dataGroup.getImportId()); - - LinkedHashMap<String, DataRef> resources = new LinkedHashMap<>(); - for (String dataFieldId : dataGroup.getData()) { - Field<?> field = net.getDataSet().get(dataFieldId); - if (!dataFieldMap.containsKey(dataFieldId)) { + private LayoutContainer processLayoutContainer(LayoutContainer container, Task task, Case useCase, String actorId, + GetLayoutsEventOutcome outcome, Locale locale, Boolean forceVisible, Set<String> collectedTaskIds) { + Map<String, DataRef> dataRefs = useCase.getProcess().getTransition(task.getTransitionId()).getDataSet(); + + container.setParentCaseId(useCase.getStringId()); + container.setParentTaskId(task.getStringId()); + container.setParentTransitionId(task.getTransitionId()); + + for (LayoutItem item : container.getItems()) { + if (item.getDataRefId() != null) { + if (!dataRefs.containsKey(item.getDataRefId())) { // This should never happen + // todo: release/8.0.0 throw an exception? + item.setDataRefId(null); + continue; + } + + Field<?> field = useCase.getDataSet().get(item.getDataRefId()); + DataFieldBehavior behavior = field.getBehaviors().get(task.getTransitionId()); + + if (behavior.isForbidden()) { continue; } - DataRef resource = dataFieldMap.get(dataFieldId); - if (level != 0) { - dataGroup.setParentCaseId(useCase.getStringId()); - resource.setParentCaseId(useCase.getStringId()); - dataGroup.setParentTaskId(taskId); - dataGroup.setParentTransitionId(task.getTransitionId()); - dataGroup.setParentTaskRefId(parentTaskRefId); - dataGroup.setNestingLevel(level); - resource.setParentTaskId(taskId); + item.setDataRef(dataRefs.get(item.getDataRefId())); + + outcome.addOutcomes(resolveDataEvents(field, DataEventType.GET, EventPhase.PRE, useCase, task, null, new HashMap<>())); + historyService.save(new GetDataEventLog(task, useCase, EventPhase.PRE, actorId)); + + if (outcome.getMessage() == null) { + setOutcomeMessage(task, useCase, outcome, item.getDataRefId(), field, DataEventType.GET); + } + item.getDataRef().setField(field); + item.getDataRef().setFieldId(item.getDataRefId()); + item.getDataRef().setBehavior(behavior); + + outcome.addOutcomes(resolveDataEvents(field, DataEventType.GET, EventPhase.POST, useCase, task, null, new HashMap<>())); + historyService.save(new GetDataEventLog(task, useCase, EventPhase.POST, actorId)); + + if (forceVisible && item.getDataRef().getBehavior().getBehavior() == FieldBehavior.EDITABLE) { + item.getDataRef().getBehavior().setBehavior(FieldBehavior.VISIBLE); } - resources.put(dataFieldId, resource); - // TODO: release/8.0.0 - // if (field.getType() == FieldType.TASK_REF && shouldResolveTaskRefData(field, transition.getDataSet().get(field.getStringId()))) { - if (field.getType() == DataType.TASK_REF) { - resultDataGroups.addAll(collectTaskRefDataGroups(dataFieldMap.get(dataFieldId), locale, collectedTaskIds, level, user)); + if (useCase.getProcess().getDataSet().get(item.getDataRefId()).getType() == DataType.TASK_REF) { + item.setContainer(this.processTaskRefLayoutContainer(item.getDataRef(), actorId, locale, collectedTaskIds, outcome)); } + } else if (item.getContainer() != null) { + item.setContainer( + this.processLayoutContainer( + item.getContainer(), task, useCase, actorId, + outcome, locale, forceVisible, collectedTaskIds + ) + ); } - dataGroup.setDataRefs(resources); } - outcome.setData(resultDataGroups); - return outcome; + return container; } - // TODO: release/8.0.0 needed? -// private boolean shouldResolveTaskRefData(Field<?> field, DataFieldLogic dataRef) { -// if (dataRef.getComponent() != null) { -// return hasRequiredComponentProperty(dataRef.getComponent(), "resolve_data", "true"); -// } else if (field.getComponent() != null) { -// return hasRequiredComponentProperty(field.getComponent(), "resolve_data", "true"); -// } -// return true; -// } - // TODO: release/8.0.0 refactor? private boolean hasRequiredComponentProperty(Component component, String propertyName, String propertyValue) { return component != null @@ -328,50 +399,37 @@ private boolean hasRequiredComponentProperty(Component component, String propert && component.getProperties().get(propertyName).equals(propertyValue); } - private List<DataGroup> collectTaskRefDataGroups(DataRef taskRefField, Locale locale, Set<String> collectedTaskIds, int level, IUser user) { + private LayoutContainer processTaskRefLayoutContainer(DataRef taskRefField, String actorId, Locale locale, Set<String> collectedTaskIds, GetLayoutsEventOutcome outcome) { List<String> taskIds = ((TaskField) taskRefField.getField()).getRawValue(); if (taskIds == null) { - return new ArrayList<>(); + return null; } - - List<DataGroup> groups = new ArrayList<>(); + LayoutContainer taskRefWrapper = new LayoutContainer(LayoutObjectType.FLEX); + taskRefWrapper.setProperties(getDefaultFlexProperties()); taskIds.stream() - .filter(id -> !collectedTaskIds.contains(id)) - .forEach(id -> { - collectedTaskIds.add(id); - List<DataGroup> taskRefDataGroups = getDataGroups(id, locale, collectedTaskIds, level + 1, taskRefField.getFieldId(), user).getData(); - resolveTaskRefBehavior(taskRefField, taskRefDataGroups); - groups.addAll(taskRefDataGroups); + .filter(taskId -> !collectedTaskIds.contains(taskId)) + .forEach(taskId -> { + collectedTaskIds.add(taskId); + LayoutItem wrapperItem = new LayoutItem(LayoutObjectType.FLEX, null, null, null, Map.of("flex-grow", "1", "flex-basis", "0")); + Task task = taskService.findOne(taskId); + Case useCase = workflowService.findOne(task.getCaseId()); + LayoutContainer container = this.processLayoutContainer( + useCase.getProcess().getTransition(task.getTransitionId()).getLayoutContainer().clone(), task, useCase, actorId, + outcome, locale, taskRefField.getBehavior().getBehavior() == FieldBehavior.VISIBLE, collectedTaskIds + ); + wrapperItem.setContainer(container); + taskRefWrapper.addLayoutItem(wrapperItem); }); - - return groups; + return taskRefWrapper; } - private void resolveTaskRefOrderOnGrid(DataGroup dataGroup, Map<String, DataRef> dataFieldMap) { - if (dataGroup.getLayout() == null || dataGroup.getLayout().getType() != LayoutType.GRID) { - return; - } - dataGroup.setData(dataGroup.getData().stream().filter(dataFieldMap::containsKey).map(dataFieldMap::get).sorted(Comparator.comparingInt(a -> a.getLayout().getY())).map(DataRef::getFieldId).collect(Collectors.toCollection(LinkedHashSet::new))); - } - - private void resolveTaskRefBehavior(DataRef taskRefField, List<DataGroup> taskRefDataGroups) { - if (taskRefField.getBehavior().getBehavior() == FieldBehavior.VISIBLE) { - taskRefDataGroups.forEach(dataGroup -> { - dataGroup.getDataRefs().values().forEach(field -> { - if (field.getBehavior().getBehavior() == FieldBehavior.EDITABLE) { - field.getBehavior().setBehavior(FieldBehavior.VISIBLE); - } - }); - }); - } else if (taskRefField.getBehavior().getBehavior() == FieldBehavior.HIDDEN) { - taskRefDataGroups.forEach(dataGroup -> { - dataGroup.getDataRefs().values().forEach(field -> { - if (field.getBehavior().getBehavior() != FieldBehavior.FORBIDDEN) { - field.getBehavior().setBehavior(FieldBehavior.HIDDEN); - } - }); - }); - } + private Map<String, String> getDefaultFlexProperties() { + Map<String, String> defaultFlexProeperties = new HashMap<>(); + defaultFlexProeperties.put("display", "flex"); + defaultFlexProeperties.put("flex-direction", "column"); + defaultFlexProeperties.put("justify-content", "flex-start"); + defaultFlexProeperties.put("align-items", "stretch"); + return defaultFlexProeperties; } @Override @@ -400,7 +458,7 @@ public FileFieldInputStream getFileByTaskAndName(String taskId, String fieldId, @Override public FileFieldInputStream getFileByCase(String caseId, Task task, String fieldId, boolean forPreview) { Case useCase = workflowService.findOne(caseId); - FileField field = (FileField) useCase.getPetriNet().getDataSet().get(fieldId); + FileField field = (FileField) useCase.getProcess().getDataSet().get(fieldId); return getFile(useCase, task, field, forPreview); } @@ -412,7 +470,7 @@ public FileFieldInputStream getFileByCaseAndName(String caseId, String fieldId, @Override public FileFieldInputStream getFileByCaseAndName(String caseId, String fieldId, String name, Map<String, String> params) { Case useCase = workflowService.findOne(caseId); - FileListField field = (FileListField) useCase.getPetriNet().getDataSet().get(fieldId); + FileListField field = (FileListField) useCase.getProcess().getDataSet().get(fieldId); return getFileByName(useCase, field, name, params); } @@ -597,8 +655,8 @@ public SetDataEventOutcome saveFiles(String taskId, String fieldId, MultipartFil private List<EventOutcome> getChangedFieldByFileFieldContainer(String fieldId, Task referencingTask, Case useCase, Map<String, String> params) { List<EventOutcome> outcomes = new ArrayList<>(); // TODO: release/8.0.0 changed value, use set data - outcomes.addAll(resolveDataEvents(useCase.getPetriNet().getField(fieldId).get(), DataEventType.SET, EventPhase.PRE, useCase, referencingTask, null, params)); - outcomes.addAll(resolveDataEvents(useCase.getPetriNet().getField(fieldId).get(), DataEventType.SET, EventPhase.POST, useCase, referencingTask, null, params)); + outcomes.addAll(resolveDataEvents(useCase.getProcess().getField(fieldId).get(), DataEventType.SET, EventPhase.PRE, useCase, referencingTask, null, params)); + outcomes.addAll(resolveDataEvents(useCase.getProcess().getField(fieldId).get(), DataEventType.SET, EventPhase.POST, useCase, referencingTask, null, params)); updateDataset(useCase); workflowService.save(useCase); return outcomes; @@ -630,9 +688,10 @@ private boolean saveLocalFiles(Case useCase, FileListField field, MultipartFile[ } private boolean saveLocalFile(Case useCase, FileField field, MultipartFile multipartFile) { - if (useCase.getDataSet().get(field.getStringId()).getRawValue() != null) { + DataFieldValue<?> fieldValue = useCase.getDataSet().get(field.getStringId()).getValue(); + if (fieldValue != null && fieldValue.getValue() != null) { new File(field.getFilePath(useCase.getStringId())).delete(); - useCase.getDataSet().get(field.getStringId()).setValue(null); + useCase.getDataSet().get(field.getStringId()).getValue().setValue(null); } field.setValue(multipartFile.getOriginalFilename()); @@ -661,19 +720,19 @@ private void writeFile(MultipartFile multipartFile, File file) throws IOExceptio fout.close(); } - protected boolean upload(Case useCase, FileField field, MultipartFile multipartFile) { + private boolean upload(Case useCase, FileField field, MultipartFile multipartFile) { throw new UnsupportedOperationException("Upload new file to the remote storage is not implemented yet."); } - protected boolean upload(Case useCase, FileListField field, MultipartFile[] multipartFiles) { + private boolean upload(Case useCase, FileListField field, MultipartFile[] multipartFiles) { throw new UnsupportedOperationException("Upload new files to the remote storage is not implemented yet."); } - protected boolean deleteRemote(Case useCase, FileField field) { + private boolean deleteRemote(Case useCase, FileField field) { throw new UnsupportedOperationException("Delete file from the remote storage is not implemented yet."); } - protected boolean deleteRemote(Case useCase, FileListField field, String name) { + private boolean deleteRemote(Case useCase, FileListField field, String name) { throw new UnsupportedOperationException("Delete file from the remote storage is not implemented yet."); } @@ -695,7 +754,7 @@ public SetDataEventOutcome deleteFile(String taskId, String fieldId, Map<String, new File(field.getRawValue().getPath()).delete(); new File(field.getFilePreviewPath(useCase.getStringId())).delete(); } - useCase.getDataSet().get(field.getStringId()).setValue(null); + useCase.getDataSet().get(field.getStringId()).getValue().setValue(null); } // TODO: release/8.0.0 6.2.5 return new SetDataEventOutcome(useCase, task, getChangedFieldByFileFieldContainer(fieldId, task, useCase, params)); @@ -731,7 +790,7 @@ public SetDataEventOutcome deleteFileByName(String taskId, String fieldId, Strin private ImmutablePair<Case, FileListField> getCaseAndFileListField(String taskId, String fieldId) { Task task = taskService.findOne(taskId); Case useCase = workflowService.findOne(task.getCaseId()); - FileListField field = (FileListField) useCase.getPetriNet().getDataSet().get(fieldId); + FileListField field = (FileListField) useCase.getProcess().getDataSet().get(fieldId); field.setRawValue(((FileListFieldValue) useCase.getDataSet().get(field.getStringId()).getRawValue())); return new ImmutablePair<>(useCase, field); } @@ -765,18 +824,10 @@ private List<EventOutcome> resolveDataEvents(Field<?> field, DataEventType trigg } @Override - public UserFieldValue makeUserFieldValue(String id) { - IUser user = userService.resolveById(id); - return new UserFieldValue(user.getStringId(), user.getName(), user.getSurname(), user.getEmail()); - } - - @Override - public Case applyFieldConnectedChanges(Case useCase, Field<?> field) { - Field<?> caseField = useCase.getDataSet().get(field.getStringId()); - if (!(caseField instanceof UserListField)) { - return useCase; - } - return workflowService.resolveUserRef(useCase); + public UserFieldValue makeUserFieldValue(String userId) { + Optional<User> userOpt = userService.findById(userId); + return userOpt.map(user -> new UserFieldValue(user.getStringId(), user.getFirstname(), + user.getLastname(), user.getEmail())).orElseGet(UserFieldValue::new); } // TODO: release/8.0.0 change component properties, parse object node diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/DataValidationExpressionEvaluator.java b/src/main/java/com/netgrif/application/engine/workflow/service/DataValidationExpressionEvaluator.java deleted file mode 100644 index 2c4e805f6be..00000000000 --- a/src/main/java/com/netgrif/application/engine/workflow/service/DataValidationExpressionEvaluator.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.netgrif.application.engine.workflow.service; - -import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ExpressionRunner; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; -import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.service.interfaces.IDataValidationExpressionEvaluator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class DataValidationExpressionEvaluator implements IDataValidationExpressionEvaluator { - - @Autowired - protected ExpressionRunner runner; - - @Override - public String compile(Case useCase, Expression expression) { - return runner.run(useCase, expression).toString(); - } - -} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/EventService.java b/src/main/java/com/netgrif/application/engine/workflow/service/EventService.java index 8c5e7de5eff..6b01a37bfdd 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/EventService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/EventService.java @@ -2,16 +2,19 @@ import com.netgrif.application.engine.importer.model.DataEventType; import com.netgrif.application.engine.petrinet.domain.DataRef; +import com.netgrif.application.engine.petrinet.domain.Function; import com.netgrif.application.engine.petrinet.domain.Transition; import com.netgrif.application.engine.petrinet.domain.dataset.Field; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionRunner; +import com.netgrif.application.engine.petrinet.domain.events.DataEvent; import com.netgrif.application.engine.petrinet.domain.events.EventPhase; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome; import com.netgrif.application.engine.workflow.service.interfaces.IEventService; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -21,17 +24,14 @@ @Slf4j @Lazy @Service +@RequiredArgsConstructor public class EventService implements IEventService { private final ActionRunner actionsRunner; - public EventService(ActionRunner actionsRunner) { - this.actionsRunner = actionsRunner; - } - @Override public List<EventOutcome> runActions(List<Action> actions, Case useCase, Task task, Transition transition, Map<String, String> params) { - log.info("[" + useCase.getStringId() + "]: Running actions of transition " + transition.getStringId()); + log.info("[{}]: Running actions of transition {}", useCase.getStringId(), transition.getStringId()); return runActions(actions, useCase, Optional.of(task), params); } @@ -43,9 +43,11 @@ public List<EventOutcome> runActions(List<Action> actions, Map<String, String> p @Override public List<EventOutcome> runActions(List<Action> actions, Case useCase, Optional<Task> task, Map<String, String> params) { List<EventOutcome> allOutcomes = new ArrayList<>(); + List<Function> functions = useCase == null ? Collections.emptyList() : useCase.getProcess().getFunctions(); actions.forEach(action -> { - List<EventOutcome> outcomes = actionsRunner.run(action, useCase, task, null, params, useCase == null ? Collections.emptyList() : useCase.getPetriNet().getFunctions()); - outcomes.stream().filter(SetDataEventOutcome.class::isInstance) + List<EventOutcome> outcomes = actionsRunner.run(action, useCase, task, null, params, functions); + outcomes.stream() + .filter(SetDataEventOutcome.class::isInstance) .forEach(outcome -> { if (((SetDataEventOutcome) outcome).getChangedFields().getFields().isEmpty()) { return; @@ -60,10 +62,12 @@ public List<EventOutcome> runActions(List<Action> actions, Case useCase, Optiona @Override public List<EventOutcome> runEventActions(Case useCase, Task task, Field<?> newDataField, List<Action> actions, DataEventType trigger, Map<String, String> params) { List<EventOutcome> allOutcomes = new ArrayList<>(); + List<Function> functions = useCase == null ? Collections.emptyList() : useCase.getProcess().getFunctions(); + Optional<Task> taskOpt = task == null ? Optional.empty() : Optional.of(task); actions.stream() .filter(a -> a.getSetDataType().isTriggered(newDataField)) .forEach(action -> { - List<EventOutcome> outcomes = actionsRunner.run(action, useCase, task == null ? Optional.empty() : Optional.of(task), newDataField, params, useCase == null ? Collections.emptyList() : useCase.getPetriNet().getFunctions()); + List<EventOutcome> outcomes = actionsRunner.run(action, useCase, taskOpt, newDataField, params, functions); outcomes.stream() .filter(SetDataEventOutcome.class::isInstance) .filter(outcome -> !((SetDataEventOutcome) outcome).getChangedFields().getFields().isEmpty()) @@ -74,15 +78,21 @@ public List<EventOutcome> runEventActions(Case useCase, Task task, Field<?> newD } @Override - public List<EventOutcome> processDataEvents(Field<?> field, DataEventType actionTrigger, EventPhase phase, Case useCase, Task task, Field<?> newDataField, Map<String, String> params) { + public List<EventOutcome> processDataEvents(Field<?> field, DataEventType actionTrigger, EventPhase phase, Case useCase, + Task task, Field<?> newDataField, Map<String, String> params) { LinkedList<Action> fieldActions = new LinkedList<>(); if (field.getEvents() != null && field.getEvents().containsKey(actionTrigger)) { fieldActions.addAll(DataRef.getEventAction(field.getEvents().get(actionTrigger), phase)); } if (task != null) { - Transition transition = useCase.getPetriNet().getTransition(task.getTransitionId()); - if (transition.getDataSet().containsKey(field.getStringId()) && !transition.getDataSet().get(field.getStringId()).getEvents().isEmpty()) { - fieldActions.addAll(DataRef.getEventAction(transition.getDataSet().get(field.getStringId()).getEvents().get(actionTrigger), phase)); + Transition transition = useCase.getProcess().getTransition(task.getTransitionId()); + boolean containsField = transition.getDataSet().containsKey(field.getStringId()); + if (containsField) { + Map<DataEventType, DataEvent> fieldEvents = transition.getDataSet().get(field.getStringId()).getEvents(); + boolean hasEvent = !fieldEvents.isEmpty() && fieldEvents.containsKey(actionTrigger); + if (hasEvent) { + fieldActions.addAll(DataRef.getEventAction(fieldEvents.get(actionTrigger), phase)); + } } } @@ -108,7 +118,7 @@ public void runEventActionsOnChanged(Task task, SetDataEventOutcome outcome, Dat .forEach(entry -> { String fieldId = entry.getKey(); Field<?> field = outcome.getCase().getDataSet().get(fieldId); - log.info("[" + outcome.getCase().getStringId() + "] " + outcome.getCase().getTitle() + ": Running actions on changed field " + fieldId); + log.info("[{}] {}: Running actions on changed field {}", outcome.getCase().getStringId(), outcome.getCase().getTitle(), fieldId); // TODO: release/8.0.0 changed fields outcome.addOutcomes(processDataEvents(field, trigger, EventPhase.PRE, outcome.getCase(), outcome.getTask(), null, params)); outcome.addOutcomes(processDataEvents(field, trigger, EventPhase.POST, outcome.getCase(), outcome.getTask(), null, params)); diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/InitValueExpressionEvaluator.java b/src/main/java/com/netgrif/application/engine/workflow/service/ExpressionEvaluator.java similarity index 63% rename from src/main/java/com/netgrif/application/engine/workflow/service/InitValueExpressionEvaluator.java rename to src/main/java/com/netgrif/application/engine/workflow/service/ExpressionEvaluator.java index bbcff42b644..be9af44bd6b 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/InitValueExpressionEvaluator.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/ExpressionEvaluator.java @@ -4,10 +4,11 @@ import com.netgrif.application.engine.petrinet.domain.dataset.ChoiceField; import com.netgrif.application.engine.petrinet.domain.dataset.Field; import com.netgrif.application.engine.petrinet.domain.dataset.MapOptionsField; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ExpressionRunner; import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ExpressionRunner; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.service.interfaces.IInitValueExpressionEvaluator; +import groovy.lang.GString; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -15,19 +16,19 @@ import java.util.stream.Collectors; @Service -public class InitValueExpressionEvaluator implements IInitValueExpressionEvaluator { +public class ExpressionEvaluator implements IInitValueExpressionEvaluator { @Autowired private ExpressionRunner runner; @Override - public <T> T evaluate(Case useCase, Field<T> defaultField, Map<String, String> params) { - return (T) evaluate(useCase, defaultField.getInitExpression(), params); + public <T> T evaluateValue(Case useCase, Field<T> defaultField, Map<String, String> params) { + return (T) runner.run(defaultField.getDefaultValue(), useCase, defaultField, params); } @Override - public Map<String, I18nString> evaluateOptions(Case useCase, MapOptionsField<I18nString, ?> field, Map<String, String> params) { - Object result = evaluate(useCase, field.getExpression(), params); + public LinkedHashMap<String, I18nString> evaluateOptions(Case useCase, MapOptionsField<I18nString, ?> field, Map<String, String> params) { + Object result = evaluate(useCase, field.getOptionsExpression(), params); if (!(result instanceof Map)) { throw new IllegalArgumentException("[" + useCase.getStringId() + "] Dynamic options not an instance of Map: " + field.getImportId()); } @@ -35,14 +36,14 @@ public Map<String, I18nString> evaluateOptions(Case useCase, MapOptionsField<I18 if (map.values().stream().anyMatch(it -> !(it instanceof I18nString))) { return map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, it -> new I18nString(it.getValue().toString()), (o1, o2) -> o1, LinkedHashMap::new)); } else { - return (Map<String, I18nString>) result; + return (LinkedHashMap<String, I18nString>) result; } } @Override - public Set<I18nString> evaluateChoices(Case useCase, ChoiceField field, Map<String, String> params) { + public <T> LinkedHashSet<I18nString> evaluateChoices(Case useCase, ChoiceField<T> field, Map<String, String> params) { Object result = evaluate(useCase, field.getExpression(), params); - if (!(result instanceof Collection)) { + if (result == null) { throw new IllegalArgumentException("[" + useCase.getStringId() + "] Dynamic choices not an instance of Collection: " + field.getImportId()); } Collection<Object> collection = (Collection) result; @@ -50,17 +51,17 @@ public Set<I18nString> evaluateChoices(Case useCase, ChoiceField field, Map<Stri } @Override - public I18nString evaluateCaseName(Case useCase, Expression expression, Map<String, String> params) { - Object result = evaluate(useCase, expression, params); - if (result instanceof I18nString) { - return (I18nString) result; - } else { - return new I18nString(result.toString()); - } + public <T> T evaluate(Case useCase, Expression<T> expression, Map<String, String> params) { + return runner.run(expression, useCase, null, params); } @Override - public Object evaluate(Case useCase, Expression expression, Map<String, String> params) { - return runner.run(useCase, expression, params); + public String evaluateTitle(Expression<String> expression, Map<String, String> params) { + Object title = this.evaluate(null, expression, params); + if (title instanceof GString) { + // due to ClassCastException + return title.toString(); + } + return (String) title; } } diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java b/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java index c8659315702..4d3b5007b0e 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java @@ -5,7 +5,7 @@ import com.netgrif.application.engine.event.IGroovyShellFactory; import com.netgrif.application.engine.petrinet.domain.Function; import com.netgrif.application.engine.petrinet.domain.FunctionScope; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.workflow.domain.CachedFunction; @@ -51,7 +51,7 @@ public void setPetriNetService(IPetriNetService petriNetService) { } @Override - public void cachePetriNetFunctions(PetriNet petriNet) { + public void cachePetriNetFunctions(Process petriNet) { if (petriNet == null) { return; } @@ -69,7 +69,7 @@ public void cachePetriNetFunctions(PetriNet petriNet) { } @Override - public void reloadCachedFunctions(PetriNet petriNet) { + public void reloadCachedFunctions(Process petriNet) { namespaceFunctionsCache.remove(petriNet.getIdentifier()); cachePetriNetFunctions(petriNetService.getNewestVersionByIdentifier(petriNet.getIdentifier())); } @@ -78,7 +78,8 @@ public void reloadCachedFunctions(PetriNet petriNet) { public Closure getCompiledAction(Action action, boolean shouldRewriteCachedActions) { String stringId = action.getId().toString(); if (shouldRewriteCachedActions || !actionsCache.containsKey(stringId)) { - Closure code = (Closure) shell.evaluate("{-> " + action.getDefinition() + "}"); + // TODO: release/8.0.0 actions and expressions + Closure code = (Closure) shell.evaluate("{-> " + action.getDefinition() + "}", action.getImportId()); actionsCache.put(stringId, code); } return actionsCache.get(stringId); diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java b/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java index c57344f216f..33543a87378 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java @@ -6,10 +6,10 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; import com.google.common.collect.Lists; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.authorization.domain.Actor; import com.netgrif.application.engine.configuration.properties.FilterProperties; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.dataset.*; import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; @@ -18,14 +18,13 @@ import com.netgrif.application.engine.workflow.domain.*; import com.netgrif.application.engine.workflow.domain.filter.FilterImportExport; import com.netgrif.application.engine.workflow.domain.filter.FilterImportExportList; -import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; import com.netgrif.application.engine.workflow.service.interfaces.IFilterImportExportService; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import javax.xml.XMLConstants; import javax.xml.transform.stream.StreamSource; @@ -60,9 +59,6 @@ public class FilterImportExportService implements IFilterImportExportService { private static final String FIELD_MISSING_ALLOWED_NETS = "missing_allowed_nets"; private static final String FIELD_MISSING_NETS_TRANSLATION = "missing_nets_translation"; - @Autowired - IUserService userService; - @Autowired IWorkflowService workflowService; @@ -76,7 +72,7 @@ public class FilterImportExportService implements IFilterImportExportService { private ITaskService taskService; @Autowired - private IDataService dataService; + private ISessionManagerService sessionManagerService; @Autowired private FileStorageConfiguration fileStorageConfiguration; @@ -85,13 +81,23 @@ public class FilterImportExportService implements IFilterImportExportService { private FilterProperties filterProperties; @Override - public void createFilterImport(IUser author) { - workflowService.createCaseByIdentifier(IMPORT_NET_IDENTIFIER, "Import filters " + author.getFullName(), "", author.transformToLoggedUser()); + public void createFilterImport(Actor author) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(IMPORT_NET_IDENTIFIER) + .title("Import filters " + author.getName()) + .authorId(author.getStringId()) + .build(); + workflowService.createCase(createCaseParams); } @Override - public void createFilterExport(IUser author) { - workflowService.createCaseByIdentifier(EXPORT_NET_IDENTIFIER, "Export filters " + author.getFullName(), "", author.transformToLoggedUser()); + public void createFilterExport(Actor author) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(EXPORT_NET_IDENTIFIER) + .title("Import filters " + author.getName()) + .authorId(author.getStringId()) + .build(); + workflowService.createCase(createCaseParams); } /** @@ -236,7 +242,8 @@ protected Map<String, String> performImport(FilterImportExportList filterList) t // filterCase.get().getDataSet().get(FIELD_FILTER).addBehavior(IMPORT_FILTER_TRANSITION, Collections.singleton(FieldBehavior.VISIBLE)); workflowService.save(filterCase.get()); }); - taskService.assignTasks(taskService.findAllById(new ArrayList<>(importedFilterTaskIds.values())), userService.getLoggedUser()); + taskService.assignTasks(taskService.findAllById(new ArrayList<>(importedFilterTaskIds.values())), + sessionManagerService.getActiveActorId(), new HashMap<>()); changeFilterField(importedFilterTaskIds.values()); return importedFilterTaskIds; } @@ -252,7 +259,7 @@ public void changeFilterField(Collection<String> filterFields) { filterFields.forEach(f -> { Task importedFilterTask = taskService.findOne(f); Case filterCase = workflowService.findOne(importedFilterTask.getCaseId()); - PetriNet filterNet = petriNetService.getNewestVersionByIdentifier(FILTER_NET_IDENTIFIER); + Process filterNet = petriNetService.getNewestVersionByIdentifier(FILTER_NET_IDENTIFIER); // TODO: release/8.0.0 // List<String> requiredNets = filterCase.getDataSet().get(FIELD_FILTER).getAllowedNets(); // List<String> currentNets = petriNetService.getExistingPetriNetIdentifiersFromIdentifiersList(requiredNets); @@ -286,11 +293,10 @@ private void changeVisibilityByAllowedNets(boolean allowedNetsMissing, Case filt // filterCase.getDataSet().get(allowedNetsMissing ? FIELD_FILTER : FIELD_MISSING_ALLOWED_NETS).makeHidden(IMPORT_FILTER_TRANSITION); } - @Transactional protected FilterImportExportList loadFromXML() throws IOException, IllegalFilterFileException { Case exportCase = workflowService.searchOne( QCase.case$.processIdentifier.eq(IMPORT_NET_IDENTIFIER) - .and(QCase.case$.author.id.eq(userService.getLoggedUser().getStringId())) + .and(QCase.case$.authorId.eq(sessionManagerService.getActiveActorId())) ); FileFieldValue ffv = ((FileField) exportCase.getDataSet().get(UPLOAD_FILE_FIELD)).getValue().getValue(); @@ -306,9 +312,8 @@ protected FilterImportExportList loadFromXML() throws IOException, IllegalFilter return xmlMapper.readValue(importedFilter, FilterImportExportList.class); } - @Transactional protected FileFieldValue createXML(FilterImportExportList filters) throws IOException { - String filePath = fileStorageConfiguration.getStoragePath() + "/filterExport/" + userService.getLoggedUser().getStringId() + "/" + filterProperties.getFileName(); + String filePath = fileStorageConfiguration.getStoragePath() + "/filterExport/" + sessionManagerService.getActiveActorId() + "/" + filterProperties.getFileName(); File f = new File(filePath); f.getParentFile().mkdirs(); diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java b/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java index f40c05a0397..4668f972121 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java @@ -5,26 +5,26 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.dataset.*; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.startup.DefaultFiltersRunner; import com.netgrif.application.engine.utils.InputStreamToString; import com.netgrif.application.engine.workflow.domain.*; import com.netgrif.application.engine.workflow.domain.menu.Menu; import com.netgrif.application.engine.workflow.domain.menu.MenuAndFilters; import com.netgrif.application.engine.workflow.domain.menu.MenuEntry; import com.netgrif.application.engine.workflow.domain.menu.MenuEntryRole; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.domain.params.TaskParams; import com.netgrif.application.engine.workflow.service.interfaces.*; import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import javax.xml.XMLConstants; import javax.xml.transform.stream.StreamSource; @@ -50,7 +50,7 @@ public class MenuImportExportService implements IMenuImportExportService { private static final String GROUP_NAV_TASK = "navigationMenuConfig"; @Autowired - IUserService userService; + ISessionManagerService sessionManagerService; @Autowired IWorkflowService workflowService; @@ -58,9 +58,6 @@ public class MenuImportExportService implements IMenuImportExportService { @Autowired IPetriNetService petriNetService; - @Autowired - DefaultFiltersRunner defaultFiltersRunner; - @Autowired private ITaskService taskService; @@ -149,7 +146,7 @@ public List<String> importMenu(List<Case> menuItemCases, FileFieldValue ffv, Str Case caseToRemove = workflowService.findOne(id); QTask qTask = new QTask("task"); Task task = taskService.searchOne(qTask.transitionId.eq("view").and(qTask.caseId.eq(caseToRemove.getStringId()))); - dataService.setData(task, caseToRemoveData, userService.getLoggedOrSystem()); + dataService.setData(new SetDataParams(task, caseToRemoveData, sessionManagerService.getActiveActorId())); }); //Import filters @@ -171,15 +168,15 @@ public List<String> importMenu(List<Case> menuItemCases, FileFieldValue ffv, Str // DataField groupImportResultMessage = new DataField(); // groupImportResultMessage.setValue(resultMessage.toString()); // groupData.getFields().put("import_results", groupImportResultMessage); - dataService.setData(task, groupData, userService.getLoggedOrSystem()); + dataService.setData(new SetDataParams(task, groupData, sessionManagerService.getActiveActorId())); }); importedFilterTaskIds.values().forEach(taskId -> { Task importedFilterTask = taskService.findOne(taskId); Case filterCase = workflowService.findOne(importedFilterTask.getCaseId()); try { - taskService.assignTask(importedFilterTask.getStringId()); - taskService.finishTask(importedFilterTask.getStringId()); + taskService.assignTask(new TaskParams(importedFilterTask.getStringId())); + taskService.finishTask(new TaskParams(importedFilterTask.getStringId())); workflowService.save(filterCase); } catch (TransitionNotExecutableException e) { log.error("Failed to execute \"import_filter\" task with id: " + taskId, e); @@ -223,40 +220,41 @@ public String createMenuItemCase(StringBuilder resultMessage, MenuEntry item, St String roleImportId = menuEntryRole.getRoleImportId(); String netImportId = menuEntryRole.getNetImportId(); if (netImportId != null) { - PetriNet net = petriNetService.getNewestVersionByIdentifier(netImportId); + Process net = petriNetService.getNewestVersionByIdentifier(netImportId); if (net == null) { resultMessage.append("\n- Missing net with import ID: \"").append(netImportId).append("\"").append("for role ").append(roleImportId).append("\n"); netCheck.set(false); } else { - Optional<ProcessRole> role = net.getRoles().values().stream().filter(r -> r.getImportId().equals(roleImportId)) - .findFirst(); - if (role.isPresent()) { - //TODO: extend funcionality - add translations to nets and roles - if (menuEntryRole.getAuthorizationType().equals(AuthorizationType.allowed)) { - allowedRoles.put(roleImportId + ":" + netImportId, new I18nString(role.get().getName() + "(" + net.getTitle() + ")")); - } else { - bannedRoles.put(roleImportId + ":" + netImportId, new I18nString(role.get().getName() + "(" + net.getTitle() + ")")); - } - } else { - resultMessage.append("\n- Role with import ID \"").append(roleImportId).append("\" ").append("does not exist in the latest present version of net \"").append(netImportId).append("\"\n"); - netCheck.set(false); - } + // TODO: release/8.0.0 fix +// Optional<ProcessRole> role = net.getRoles().values().stream().filter(r -> r.getImportId().equals(roleImportId)) +// .findFirst(); +// if (role.isPresent()) { +// TODO: extend funcionality - add translations to nets and roles +// if (menuEntryRole.getAuthorizationType().equals(AuthorizationType.allowed)) { +// allowedRoles.put(roleImportId + ":" + netImportId, new I18nString(role.get().getName() + "(" + net.getTitle() + ")")); +// } else { +// bannedRoles.put(roleImportId + ":" + netImportId, new I18nString(role.get().getName() + "(" + net.getTitle() + ")")); +// } +// } else { +// resultMessage.append("\n- Role with import ID \"").append(roleImportId).append("\" ").append("does not exist in the latest present version of net \"").append(netImportId).append("\"\n"); +// netCheck.set(false); +// } } } }); } //Creating new Case of preference_filter_item net and setting its data... - Case menuItemCase = workflowService.createCase( - petriNetService.getNewestVersionByIdentifier("preference_filter_item").getStringId(), - item.getEntryName() + "_" + menuIdentifier, - "", - userService.getSystem().transformToLoggedUser() - ).getCase(); + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(petriNetService.getNewestVersionByIdentifier("preference_filter_item")) + .title(item.getEntryName() + "_" + menuIdentifier) + .authorId(sessionManagerService.getActiveActorId()) + .build(); + Case menuItemCase = workflowService.createCase(createCaseParams).getCase(); QTask qTask = new QTask("task"); Task task = taskService.searchOne(qTask.transitionId.eq("init").and(qTask.caseId.eq(menuItemCase.getStringId()))); try { - taskService.assignTask(task, userService.getLoggedUser()); + taskService.assignTask(new TaskParams(task, sessionManagerService.getActiveActorId())); // TODO: release/8.0.0 // menuItemCase.getDataSet().get(MENU_IDENTIFIER).setValue(menuIdentifier); // menuItemCase.getDataSet().get(PARENT_ID).setValue(parentId); @@ -273,8 +271,7 @@ public String createMenuItemCase(StringBuilder resultMessage, MenuEntry item, St return task.getCaseId() + "," + filterCase.getStringId() + "," + item.getUseIcon().toString(); } - @Transactional - protected MenuAndFilters loadFromXML(FileFieldValue ffv) throws IOException, IllegalMenuFileException { + private MenuAndFilters loadFromXML(FileFieldValue ffv) throws IOException, IllegalMenuFileException { File f = new File(ffv.getPath()); validateFilterXML(new FileInputStream(f)); SimpleModule module = new SimpleModule().addDeserializer(Object.class, FilterDeserializer.getInstance()); @@ -283,11 +280,10 @@ protected MenuAndFilters loadFromXML(FileFieldValue ffv) throws IOException, Ill return xmlMapper.readValue(xml, MenuAndFilters.class); } - @Transactional - protected FileFieldValue createXML(MenuAndFilters menuAndFilters, String parentId, FileField fileField) throws IOException { + private FileFieldValue createXML(MenuAndFilters menuAndFilters, String parentId, FileField fileField) throws IOException { FileFieldValue ffv = new FileFieldValue(); try { - ffv.setName("menu_" + userService.getLoggedUser().getFullName().replaceAll("\\s+", "") + ".xml"); + ffv.setName("menu_" + sessionManagerService.getLoggedIdentity().getUsername().replaceAll("\\s+", "") + ".xml"); ffv.setPath(FileStorageConfiguration.getPath(parentId, fileField.getImportId(), ffv.getName())); File f = new File(ffv.getPath()); XmlMapper xmlMapper = new XmlMapper(); @@ -353,7 +349,7 @@ public Map<String, I18nString> createAvailableEntriesChoices(List<Case> menuItem public Map<String, I18nString> addSelectedEntriesToExport(MultichoiceMapField availableEntries, EnumerationMapField menusForExport, String menuIdentifier) { Map<String, I18nString> updatedOptions = new LinkedHashMap<>(menusForExport.getOptions()); String menuCaseIds = ""; - if (availableEntries.getOptions().size() != 0) { + if (!availableEntries.getOptions().isEmpty()) { for (String id : availableEntries.getValue().getValue()) { menuCaseIds = menuCaseIds.concat(id + ","); } diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/MongoSearchService.java b/src/main/java/com/netgrif/application/engine/workflow/service/MongoSearchService.java index bde00d68e71..00e41ae4875 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/MongoSearchService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/MongoSearchService.java @@ -1,7 +1,5 @@ package com.netgrif.application.engine.workflow.service; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.querydsl.core.BooleanBuilder; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -26,9 +24,6 @@ public class MongoSearchService<T> { private static final String ERROR_KEY = "ERROR"; - @Autowired - private IUserService userService; - @Autowired private MongoTemplate mongoTemplate; diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/SystemCaseFactoryRegistry.java b/src/main/java/com/netgrif/application/engine/workflow/service/SystemCaseFactoryRegistry.java new file mode 100644 index 00000000000..bed02433efd --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/service/SystemCaseFactoryRegistry.java @@ -0,0 +1,48 @@ +package com.netgrif.application.engine.workflow.service; + +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.SystemCase; +import com.netgrif.application.engine.workflow.service.factory.SystemCaseFactory; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Slf4j +@Service +public class SystemCaseFactoryRegistry { + + /** + * Key is a process identifier and value is a factory + * */ + private final Map<String, SystemCaseFactory<?>> factories; + + public SystemCaseFactoryRegistry() { + this.factories = new ConcurrentHashMap<>(); + } + + /** + * todo javadoc + * */ + public void registerFactory(String processIdentifier, SystemCaseFactory<?> factory) { + this.factories.put(processIdentifier, factory); + log.debug("Registered system case factory [{}] for process [{}].", factory.getClass(), processIdentifier); + } + + /** + * todo javadoc + * */ + public SystemCase fromCase(Case systemCase) { + if (systemCase == null) { + return null; + } + SystemCaseFactory<?> factory = this.factories.get(systemCase.getProcessIdentifier()); + if (factory == null) { + log.warn("System case with id [{}] of [{}] hasn't got registered factory", systemCase.getStringId(), + systemCase.getProcessIdentifier()); + return null; + } + return factory.createObject(systemCase); + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java b/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java deleted file mode 100644 index 076dc4f3838..00000000000 --- a/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.netgrif.application.engine.workflow.service; - -import com.netgrif.application.engine.auth.domain.AnonymousUser; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.petrinet.domain.roles.AssignedUserPermission; -import com.netgrif.application.engine.petrinet.domain.roles.RolePermission; -import com.netgrif.application.engine.petrinet.domain.throwable.IllegalTaskStateException; -import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.service.interfaces.ITaskAuthorizationService; -import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.Arrays; -import java.util.Map; - -@Service -public class TaskAuthorizationService extends AbstractAuthorizationService implements ITaskAuthorizationService { - - @Autowired - ITaskService taskService; - - @Override - public Boolean userHasAtLeastOneRolePermission(LoggedUser loggedUser, String taskId, RolePermission... permissions) { - return userHasAtLeastOneRolePermission(loggedUser.transformToUser(), taskService.findById(taskId), permissions); - } - - @Override - public Boolean userHasAtLeastOneRolePermission(IUser user, Task task, RolePermission... permissions) { - if (task.getRoles() == null || task.getRoles().isEmpty()) { - return null; - } - - Map<RolePermission, Boolean> aggregatePermissions = getAggregateRolePermissions(user, task.getRoles()); - - for (RolePermission permission : permissions) { - if (hasRestrictedPermission(aggregatePermissions.get(permission))) { - return false; - } - } - - return Arrays.stream(permissions).anyMatch(permission -> hasPermission(aggregatePermissions.get(permission))); - } - - @Override - public Boolean userHasUserListPermission(LoggedUser loggedUser, String taskId, RolePermission... permissions) { - return userHasUserListPermission(loggedUser.transformToUser(), taskService.findById(taskId), permissions); - } - - @Override - public Boolean userHasUserListPermission(IUser user, Task task, RolePermission... permissions) { - if (task.getUserRefs() == null || task.getUserRefs().isEmpty()) { - return null; - } - - if (!task.getUsers().containsKey(user.getSelfOrImpersonated().getStringId())) { - return null; - } - - Map<RolePermission, Boolean> userPermissions = task.getUsers().get(user.getSelfOrImpersonated().getStringId()); - - for (RolePermission permission : permissions) { - Boolean perm = userPermissions.get(permission); - if (hasRestrictedPermission(perm)) { - return false; - } - } - return Arrays.stream(permissions).anyMatch(permission -> hasPermission(userPermissions.get(permission))); - } - - @Override - public boolean isAssignee(LoggedUser loggedUser, String taskId) { - if (loggedUser.isAnonymous()) { - return isAssignee(loggedUser.transformToAnonymousUser(), taskService.findById(taskId)); - } - return isAssignee(loggedUser.transformToUser(), taskService.findById(taskId)); - } - - @Override - public boolean isAssignee(IUser user, String taskId) { - return isAssignee(user, taskService.findById(taskId)); - } - - @Override - public boolean isAssignee(IUser user, Task task) { - if (!isAssigned(task)) { - return false; - } - return task.getUserId().equals(user.getSelfOrImpersonated().getStringId()) || user instanceof AnonymousUser; - } - - private boolean isAssigned(String taskId) { - return isAssigned(taskService.findById(taskId)); - } - - private boolean isAssigned(Task task) { - return task.getUserId() != null; - } - - @Override - public boolean canCallAssign(LoggedUser loggedUser, String taskId) { - Boolean rolePerm = userHasAtLeastOneRolePermission(loggedUser, taskId, RolePermission.ASSIGN); - Boolean userPerm = userHasUserListPermission(loggedUser, taskId, RolePermission.ASSIGN); - return loggedUser.getSelfOrImpersonated().isAdmin() || (userPerm == null ? (rolePerm != null && rolePerm) : userPerm); - } - - @Override - public boolean canCallDelegate(LoggedUser loggedUser, String taskId) { - Boolean rolePerm = userHasAtLeastOneRolePermission(loggedUser, taskId, RolePermission.DELEGATE); - Boolean userPerm = userHasUserListPermission(loggedUser, taskId, RolePermission.DELEGATE); - return loggedUser.getSelfOrImpersonated().isAdmin() || (userPerm == null ? (rolePerm != null && rolePerm) : userPerm); - } - - @Override - public boolean canCallFinish(LoggedUser loggedUser, String taskId) throws IllegalTaskStateException { - if (!isAssigned(taskId)) { - throw new IllegalTaskStateException("Task with ID '" + taskId + "' cannot be finished, because it is not assigned!"); - } - Boolean rolePerm = userHasAtLeastOneRolePermission(loggedUser, taskId, RolePermission.FINISH); - Boolean userPerm = userHasUserListPermission(loggedUser, taskId, RolePermission.FINISH); - return loggedUser.getSelfOrImpersonated().isAdmin() || ((userPerm == null ? (rolePerm != null && rolePerm) : userPerm) && isAssignee(loggedUser, taskId)); - } - - private boolean canAssignedCancel(IUser user, String taskId) { - Task task = taskService.findById(taskId); - if (!isAssigned(task) || !task.getUserId().equals(user.getSelfOrImpersonated().getStringId())) { - return true; - } - return (task.getAssignedUserPolicy() == null || task.getAssignedUserPolicy().get(AssignedUserPermission.CANCEL) == null) || task.getAssignedUserPolicy().get(AssignedUserPermission.CANCEL); - } - - @Override - public boolean canCallCancel(LoggedUser loggedUser, String taskId) throws IllegalTaskStateException { - if (!isAssigned(taskId)) { - throw new IllegalTaskStateException("Task with ID '" + taskId + "' cannot be canceled, because it is not assigned!"); - } - Boolean rolePerm = userHasAtLeastOneRolePermission(loggedUser, taskId, RolePermission.CANCEL); - Boolean userPerm = userHasUserListPermission(loggedUser, taskId, RolePermission.CANCEL); - return loggedUser.getSelfOrImpersonated().isAdmin() || ((userPerm == null ? (rolePerm != null && rolePerm) : userPerm) && isAssignee(loggedUser, taskId)) && canAssignedCancel(loggedUser.transformToUser(), taskId); - } - - @Override - public boolean canCallSaveData(LoggedUser loggedUser, String taskId) { - return loggedUser.getSelfOrImpersonated().isAdmin() || isAssignee(loggedUser, taskId); - } - - @Override - public boolean canCallSaveFile(LoggedUser loggedUser, String taskId) { - return loggedUser.getSelfOrImpersonated().isAdmin() || isAssignee(loggedUser, taskId); - } -} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/TaskEventHandler.java b/src/main/java/com/netgrif/application/engine/workflow/service/TaskEventHandler.java index 2291db40ca4..879387dfca3 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/TaskEventHandler.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/TaskEventHandler.java @@ -3,37 +3,33 @@ import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskMappingService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; import com.netgrif.application.engine.workflow.domain.Task; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.bson.Document; import org.bson.types.ObjectId; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; import org.springframework.data.mongodb.core.mapping.event.AfterDeleteEvent; import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionalEventListener; @Slf4j @Component -public class TaskEventHandler extends AbstractMongoEventListener<Task> { +@RequiredArgsConstructor +public class TaskEventHandler { - @Autowired - private IElasticTaskService service; + private final IElasticTaskService service; + private final IElasticTaskMappingService taskMappingService; - @Autowired - private IElasticTaskMappingService taskMappingService; - - @Async - @Override + @TransactionalEventListener(fallbackExecution = true, condition = "#event.collectionName == 'task'") public void onAfterSave(AfterSaveEvent<Task> event) { service.index(this.taskMappingService.transform(event.getSource())); } - @Override + @TransactionalEventListener(fallbackExecution = true, condition = "#event.collectionName == 'task'") public void onAfterDelete(AfterDeleteEvent<Task> event) { Document document = event.getDocument(); - if (document == null) { - log.warn("Trying to delete null document!"); + if (document == null || document.isEmpty()) { + log.warn("Trying to delete null or empty document!"); return; } diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/TaskSearchService.java b/src/main/java/com/netgrif/application/engine/workflow/service/TaskSearchService.java index 363dc7e2a74..56dd174b708 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/TaskSearchService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/TaskSearchService.java @@ -1,39 +1,37 @@ package com.netgrif.application.engine.workflow.service; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.petrinet.domain.PetriNetSearch; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleAssignmentService; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference; -import com.netgrif.application.engine.utils.FullPageRequest; import com.netgrif.application.engine.workflow.domain.QTask; +import com.netgrif.application.engine.workflow.domain.State; import com.netgrif.application.engine.workflow.domain.Task; import com.netgrif.application.engine.workflow.web.requestbodies.TaskSearchRequest; import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.TaskSearchCaseRequest; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Predicate; +import lombok.RequiredArgsConstructor; import org.bson.types.ObjectId; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; @Service +@RequiredArgsConstructor public class TaskSearchService extends MongoSearchService<Task> { - @Autowired - private IPetriNetService petriNetService; + private final IPetriNetService petriNetService; + private final IRoleAssignmentService roleAssignmentService; - public Predicate buildQuery(List<TaskSearchRequest> requests, LoggedUser user, Locale locale, Boolean isIntersection) { - LoggedUser loggedOrImpersonated = user.getSelfOrImpersonated(); - List<Predicate> singleQueries = requests.stream().map(r -> this.buildSingleQuery(r, loggedOrImpersonated, locale)).collect(Collectors.toList()); + public Predicate buildQuery(List<TaskSearchRequest> requests, String actorId, Locale locale, Boolean isIntersection) { + List<Predicate> singleQueries = requests.stream().map(r -> this.buildSingleQuery(r, actorId, locale)).collect(Collectors.toList()); if (isIntersection && !singleQueries.stream().allMatch(Objects::nonNull)) { // one of the queries evaluates to empty set => the entire result is an empty set return null; } else if (!isIntersection) { singleQueries = singleQueries.stream().filter(Objects::nonNull).collect(Collectors.toList()); - if (singleQueries.size() == 0) { + if (singleQueries.isEmpty()) { // all queries result in an empty set => the entire result is an empty set return null; } @@ -41,83 +39,84 @@ public Predicate buildQuery(List<TaskSearchRequest> requests, LoggedUser user, L BooleanBuilder builder = constructPredicateTree(singleQueries, isIntersection ? BooleanBuilder::and : BooleanBuilder::or); - BooleanBuilder constraints = new BooleanBuilder(buildRolesQueryConstraint(loggedOrImpersonated)); - constraints.or(buildUserRefQueryConstraint(loggedOrImpersonated)); - builder.and(constraints); - - BooleanBuilder permissionConstraints = new BooleanBuilder(buildViewRoleQueryConstraint(loggedOrImpersonated)); - permissionConstraints.andNot(buildNegativeViewRoleQueryConstraint(loggedOrImpersonated)); - permissionConstraints.or(buildViewUserQueryConstraint(loggedOrImpersonated)); - permissionConstraints.andNot(buildNegativeViewUsersQueryConstraint(loggedOrImpersonated)); - builder.and(permissionConstraints); +// final Set<String> assignedRoleIds = roleAssignmentService.findAllRoleIdsByActorAndGroups(actorId); +// BooleanBuilder constraints = new BooleanBuilder(buildProcessRolesQueryConstraint(assignedRoleIds)); +// constraints.or(buildCaseRolesQueryConstraint(assignedRoleIds)); +// builder.and(constraints); +// BooleanBuilder permissionConstraints = new BooleanBuilder(buildPositiveProcessRoleQueryConstraint(assignedRoleIds)); +// permissionConstraints.andNot(buildNegativeProcessRoleQueryConstraint(assignedRoleIds)); +// permissionConstraints.or(buildPositiveCaseRoleQueryConstraint(assignedRoleIds)); +// permissionConstraints.andNot(buildNegativeCaseRoleQueryConstraint(assignedRoleIds)); +// builder.and(permissionConstraints); return builder; } - protected Predicate buildRolesQueryConstraint(LoggedUser user) { - List<Predicate> roleConstraints = user.getProcessRoles().stream().map(this::roleQuery).collect(Collectors.toList()); - return constructPredicateTree(roleConstraints, BooleanBuilder::or); - } - - protected Predicate buildUserRefQueryConstraint(LoggedUser user) { - Predicate userRefConstraints = userRefQuery(user.getId()); - return constructPredicateTree(Collections.singletonList(userRefConstraints), BooleanBuilder::or); - } - - protected Predicate buildViewRoleQueryConstraint(LoggedUser user) { - List<Predicate> roleConstraints = user.getProcessRoles().stream().map(this::viewRoleQuery).collect(Collectors.toList()); - return constructPredicateTree(roleConstraints, BooleanBuilder::or); - } - - public Predicate viewRoleQuery(String role) { - return QTask.task.viewUserRefs.isEmpty().and(QTask.task.viewRoles.isEmpty()).or(QTask.task.viewRoles.contains(role)); - } - - protected Predicate buildViewUserQueryConstraint(LoggedUser user) { - Predicate userConstraints = viewUsersQuery(user.getId()); - return constructPredicateTree(Collections.singletonList(userConstraints), BooleanBuilder::or); - } - - public Predicate viewUsersQuery(String userId) { - return QTask.task.negativeViewRoles.isEmpty().and(QTask.task.viewUserRefs.isEmpty()).and(QTask.task.viewRoles.isEmpty()).or(QTask.task.viewUsers.contains(userId)); - } - - protected Predicate buildNegativeViewRoleQueryConstraint(LoggedUser user) { - List<Predicate> roleConstraints = user.getProcessRoles().stream().map(this::negativeViewRoleQuery).collect(Collectors.toList()); - return constructPredicateTree(roleConstraints, BooleanBuilder::or); - } - - public Predicate negativeViewRoleQuery(String role) { - return QTask.task.negativeViewRoles.contains(role); - } - - protected Predicate buildNegativeViewUsersQueryConstraint(LoggedUser user) { - Predicate userConstraints = negativeViewUsersQuery(user.getId()); - return constructPredicateTree(Collections.singletonList(userConstraints), BooleanBuilder::or); - } - - public Predicate negativeViewUsersQuery(String userId) { - return QTask.task.negativeViewUsers.contains(userId); - } - - - private Predicate buildSingleQuery(TaskSearchRequest request, LoggedUser user, Locale locale) { +// protected Predicate buildProcessRolesQueryConstraint(Set<String> assignedRoleIds) { +// List<Predicate> roleConstraints = assignedRoleIds.stream().map(this::processRoleQuery).collect(Collectors.toList()); +// return constructPredicateTree(roleConstraints, BooleanBuilder::or); +// } +// +// protected Predicate buildCaseRolesQueryConstraint(Set<String> assignedRoleIds) { +// List<Predicate> roleConstraints = assignedRoleIds.stream().map(this::caseRoleQuery).collect(Collectors.toList()); +// return constructPredicateTree(roleConstraints, BooleanBuilder::or); +// } +// +// protected Predicate buildPositiveProcessRoleQueryConstraint(Set<String> assignedRoleIds) { +// List<Predicate> roleConstraints = assignedRoleIds.stream().map(this::positiveProcessRoleQuery).collect(Collectors.toList()); +// return constructPredicateTree(roleConstraints, BooleanBuilder::or); +// } +// +// protected Predicate buildPositiveCaseRoleQueryConstraint(Set<String> assignedRoleIds) { +// Predicate userConstraints = positiveCaseRoleQuery(user.getId()); +// return constructPredicateTree(Collections.singletonList(userConstraints), BooleanBuilder::or); +// } +// +// protected Predicate buildNegativeProcessRoleQueryConstraint(Set<String> assignedRoleIds) { +// List<Predicate> roleConstraints = user.getProcessRoles().stream().map(this::negativeViewRoleQuery).collect(Collectors.toList()); +// return constructPredicateTree(roleConstraints, BooleanBuilder::or); +// } +// +// protected Predicate buildNegativeCaseRoleQueryConstraint(Set<String> assignedRoleIds) { +// Predicate userConstraints = negativeViewUsersQuery(user.getId()); +// return constructPredicateTree(Collections.singletonList(userConstraints), BooleanBuilder::or); +// } +// +// public Predicate positiveProcessRoleQuery(String roleId) { +// // todo: release/8.0.0 view_disabled +// return QTask.task.caseRolePermissions.permissions.isEmpty().and(QTask.task.processRolePermissions.permissions.isEmpty()) +// .or(QTask.task.processRolePermissions.permissions.get(roleId).eq(Map.of(TaskPermission.VIEW, true))); +// } +// +// public Predicate positiveCaseRoleQuery(String userId) { +// return QTask.task.caseRolePermissions.permissions.isEmpty().and(QTask.task.processRolePermissions.permissions.isEmpty()) +// .or(QTask.task.processRolePermissions.permissions.get(roleId).eq(Map.of(TaskPermission.VIEW, true))); +// return QTask.task.negativeViewRoles.isEmpty().and(QTask.task.viewUserRefs.isEmpty()).and(QTask.task.viewRoles.isEmpty()).or(QTask.task.viewUsers.contains(userId)); +// } +// +// public Predicate negativeViewRoleQuery(String role) { +// return QTask.task.negativeViewRoles.contains(role); +// } +// +// public Predicate negativeViewUsersQuery(String userId) { +// return QTask.task.negativeViewUsers.contains(userId); +// } + + + private Predicate buildSingleQuery(TaskSearchRequest request, String actorId, Locale locale) { BooleanBuilder builder = new BooleanBuilder(); buildStringIdQuery(request, builder); - buildRoleQuery(request, builder); + buildStateQuery(request, builder); +// buildRoleQuery(request, builder); buildCaseQuery(request, builder); buildTitleQuery(request, builder); - buildUserQuery(request, builder); + buildAssigneeQuery(request, builder); buildProcessQuery(request, builder); buildFullTextQuery(request, builder); buildTransitionQuery(request, builder); - buildTagsQuery(request, builder); - boolean resultAlwaysEmpty = buildGroupQuery(request, user, locale, builder); + buildPropertiesQuery(request, builder); - if (resultAlwaysEmpty) - return null; - else - return builder; + return builder; } private void buildStringIdQuery(TaskSearchRequest request, BooleanBuilder query) { @@ -132,28 +131,44 @@ private void buildStringIdQuery(TaskSearchRequest request, BooleanBuilder query) ); } - private void buildRoleQuery(TaskSearchRequest request, BooleanBuilder query) { - if (request.role == null || request.role.isEmpty()) { + private void buildStateQuery(TaskSearchRequest request, BooleanBuilder query) { + if (request.state == null || request.state.isEmpty()) { return; } query.and( constructPredicateTree( - request.role.stream().map(this::roleQuery).collect(Collectors.toList()), + request.state.stream().map(this::stateQuery).collect(Collectors.toList()), BooleanBuilder::or) ); } - - public Predicate roleQuery(String role) { - return QTask.task.roles.containsKey(role); - } - +// +// private void buildRoleQuery(TaskSearchRequest request, BooleanBuilder query) { +// if (request.role == null || request.role.isEmpty()) { +// return; +// } +// +// query.and( +// constructPredicateTree( +// request.role.stream().map(this::roleQuery).collect(Collectors.toList()), +// BooleanBuilder::or) +// ); +// } +// +// public Predicate processRoleQuery(String roleId) { +// return QTask.task.processRolePermissions.permissions.containsKey(roleId); +// } +// +// public Predicate caseRoleQuery(String roleId) { +// return QTask.task.caseRolePermissions.permissions.containsKey(roleId); +// } +// public Predicate stringIdQuery(String id) { return QTask.task.id.eq(new ObjectId(id)); } - public Predicate userRefQuery(String userId) { - return QTask.task.users.containsKey(userId); + public Predicate stateQuery(State state) { + return QTask.task.state.eq(state); } private void buildCaseQuery(TaskSearchRequest request, BooleanBuilder query) { @@ -175,9 +190,9 @@ private void buildCaseQuery(TaskSearchRequest request, BooleanBuilder query) { private Predicate caseRequestQuery(TaskSearchCaseRequest caseRequest) { if (caseRequest.id != null) { return caseIdQuery(caseRequest.id); - } else if (caseRequest.title != null) { + } /*else if (caseRequest.title != null) { return caseTitleQuery(caseRequest.title); - } + }*/ return null; } @@ -185,9 +200,9 @@ public Predicate caseIdQuery(String caseId) { return QTask.task.caseId.eq(caseId); } - public Predicate caseTitleQuery(String caseTitle) { - return QTask.task.caseTitle.containsIgnoreCase(caseTitle); - } +// public Predicate caseTitleQuery(String caseTitle) { +// return QTask.task.containsIgnoreCase(caseTitle); +// } private void buildTitleQuery(TaskSearchRequest request, BooleanBuilder query) { if (request.title == null || request.title.isEmpty()) { @@ -205,20 +220,20 @@ public Predicate titleQuery(String query) { return QTask.task.title.defaultValue.containsIgnoreCase(query); } - private void buildUserQuery(TaskSearchRequest request, BooleanBuilder query) { - if (request.user == null || request.user.isEmpty()) { + private void buildAssigneeQuery(TaskSearchRequest request, BooleanBuilder query) { + if (request.assigneeId == null || request.assigneeId.isEmpty()) { return; } query.and( constructPredicateTree( - request.user.stream().map(this::userQuery).collect(Collectors.toList()), + request.assigneeId.stream().map(this::assigneeQuery).collect(Collectors.toList()), BooleanBuilder::or) ); } - public Predicate userQuery(String userId) { - return QTask.task.userId.eq(userId); + public Predicate assigneeQuery(String assigneeId) { + return QTask.task.assigneeId.eq(assigneeId); } private void buildProcessQuery(TaskSearchRequest request, BooleanBuilder query) { @@ -248,7 +263,7 @@ private void buildFullTextQuery(TaskSearchRequest request, BooleanBuilder query) public Predicate fullTextQuery(String searchedText) { BooleanBuilder builder = new BooleanBuilder(); builder.or(QTask.task.title.defaultValue.containsIgnoreCase(searchedText)); - builder.or(QTask.task.caseTitle.containsIgnoreCase(searchedText)); +// builder.or(QTask.task.caseTitle.containsIgnoreCase(searchedText)); return builder; } @@ -268,38 +283,19 @@ public Predicate transitionQuery(String transitionId) { return QTask.task.transitionId.eq(transitionId); } - public boolean buildGroupQuery(TaskSearchRequest request, LoggedUser user, Locale locale, BooleanBuilder query) { - if (request.group == null || request.group.isEmpty()) - return false; - - PetriNetSearch processQuery = new PetriNetSearch(); - processQuery.setGroup(request.group); - List<PetriNetReference> groupProcesses = this.petriNetService.search(processQuery, user, new FullPageRequest(), locale).getContent(); - if (groupProcesses.size() == 0) - return true; - - query.and( - constructPredicateTree( - groupProcesses.stream().map(PetriNetReference::getStringId).map(QTask.task.processId::eq).collect(Collectors.toList()), - BooleanBuilder::or - ) - ); - return false; - } - - private void buildTagsQuery(TaskSearchRequest request, BooleanBuilder query) { - if (request.tags == null || request.tags.isEmpty()) { + private void buildPropertiesQuery(TaskSearchRequest request, BooleanBuilder query) { + if (request.properties == null || request.properties.isEmpty()) { return; } query.and( constructPredicateTree( - request.tags.entrySet().stream().map(entry -> this.tagQuery(entry.getKey(), entry.getValue())).collect(Collectors.toList()), + request.properties.entrySet().stream().map(entry -> this.tagQuery(entry.getKey(), entry.getValue())).collect(Collectors.toList()), BooleanBuilder::and) ); } public Predicate tagQuery(String key, String value) { - return QTask.task.tags.get(key).eq(value); + return QTask.task.properties.get(key).eq(value); } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/TaskService.java b/src/main/java/com/netgrif/application/engine/workflow/service/TaskService.java index b8045e2533c..f0b6e623c0c 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/TaskService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/TaskService.java @@ -1,44 +1,39 @@ package com.netgrif.application.engine.workflow.service; import com.google.common.collect.Ordering; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskMappingService; -import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; +import com.netgrif.application.engine.authorization.domain.User; +import com.netgrif.application.engine.authorization.domain.permissions.AccessPermissions; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; import com.netgrif.application.engine.history.domain.taskevents.AssignTaskEventLog; import com.netgrif.application.engine.history.domain.taskevents.CancelTaskEventLog; -import com.netgrif.application.engine.history.domain.taskevents.DelegateTaskEventLog; import com.netgrif.application.engine.history.domain.taskevents.FinishTaskEventLog; import com.netgrif.application.engine.history.service.IHistoryService; import com.netgrif.application.engine.importer.model.EventType; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.petrinet.domain.Place; -import com.netgrif.application.engine.petrinet.domain.Transaction; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; import com.netgrif.application.engine.petrinet.domain.Transition; -import com.netgrif.application.engine.petrinet.domain.arcs.Arc; -import com.netgrif.application.engine.petrinet.domain.arcs.ArcOrderComparator; -import com.netgrif.application.engine.petrinet.domain.arcs.ResetArc; +import com.netgrif.application.engine.petrinet.domain.arcs.*; import com.netgrif.application.engine.petrinet.domain.dataset.UserFieldValue; -import com.netgrif.application.engine.petrinet.domain.dataset.UserListField; import com.netgrif.application.engine.petrinet.domain.dataset.UserListFieldValue; import com.netgrif.application.engine.petrinet.domain.events.EventPhase; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.petrinet.domain.roles.RolePermission; +import com.netgrif.application.engine.petrinet.domain.throwable.IllegalMarkingException; import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; import com.netgrif.application.engine.rules.domain.facts.TransitionEventFact; import com.netgrif.application.engine.rules.service.interfaces.IRuleEngine; +import com.netgrif.application.engine.transaction.NaeTransaction; +import com.netgrif.application.engine.transaction.configuration.NaeTransactionProperties; import com.netgrif.application.engine.utils.DateUtils; import com.netgrif.application.engine.utils.FullPageRequest; -import com.netgrif.application.engine.validation.service.interfaces.IValidationService; -import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.State; -import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.TaskNotFoundException; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.*; +import com.netgrif.application.engine.workflow.domain.*; +import com.netgrif.application.engine.workflow.domain.outcomes.CreateTasksOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.DoEventTaskOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.UpdateTaskStateOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.GetDataEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.*; +import com.netgrif.application.engine.workflow.domain.params.GetDataParams; +import com.netgrif.application.engine.workflow.domain.params.TaskParams; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.workflow.domain.repositories.TaskRepository; import com.netgrif.application.engine.workflow.domain.triggers.AutoTrigger; import com.netgrif.application.engine.workflow.domain.triggers.TimeTrigger; @@ -49,349 +44,481 @@ import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import com.netgrif.application.engine.workflow.web.requestbodies.TaskSearchRequest; import com.netgrif.application.engine.workflow.web.responsebodies.TaskReference; +import groovy.lang.Closure; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.query.BasicQuery; +import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionSynchronizationManager; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; import java.util.*; -import java.util.function.Predicate; -import java.util.function.Supplier; import java.util.stream.Collectors; -import java.util.stream.Stream; @Slf4j @Service public class TaskService implements ITaskService { @Autowired - protected ApplicationEventPublisher publisher; + private TaskRepository taskRepository; @Autowired - protected TaskRepository taskRepository; - - @Autowired - protected IUserService userService; - - @Autowired - protected MongoTemplate mongoTemplate; - - @Autowired - protected TaskSearchService searchService; + private TaskSearchService searchService; @Autowired @Qualifier("taskScheduler") - protected TaskScheduler scheduler; + private TaskScheduler scheduler; @Autowired - protected IWorkflowService workflowService; + private IWorkflowService workflowService; @Autowired - protected IDataService dataService; + private IDataService dataService; @Autowired - protected IProcessRoleService processRoleService; + private IEventService eventService; @Autowired - protected IElasticTaskMappingService taskMappingService; + private IHistoryService historyService; @Autowired - protected IEventService eventService; - - protected IElasticTaskService elasticTaskService; + private ISessionManagerService sessionManagerService; @Autowired - protected IHistoryService historyService; + private IUserService userService; @Autowired - protected IValidationService validation; + private MongoTransactionManager transactionManager; @Autowired - public void setElasticTaskService(IElasticTaskService elasticTaskService) { - this.elasticTaskService = elasticTaskService; - } + private NaeTransactionProperties transactionProperties; @Autowired private IRuleEngine ruleEngine; + /** + * Executes provided {@link Task} in provided {@link Case} + * + * @param task Task to be executed + * @param useCase Case where the task exists + * + * @return list of outcomes from the triggered events during the task execution + * */ @Override - public List<AssignTaskEventOutcome> assignTasks(List<Task> tasks, IUser user) throws TransitionNotExecutableException { - return assignTasks(tasks, user, new HashMap<>()); + public List<EventOutcome> executeTask(Task task, Case useCase) { + log.info("[{}]: executeTask [{}] in case [{}]", useCase.getStringId(), task.getTransitionId(), useCase.getTitle()); + List<EventOutcome> outcomes = new ArrayList<>(); + try { + log.info("assignTask [{}] in case [{}]", task.getTitle(), useCase.getTitle()); + AssignTaskEventOutcome assignOutcome = assignTask(new TaskParams(task)); + outcomes.add(assignOutcome); + log.info("getData [{}] in case [{}]", task.getTitle(), useCase.getTitle()); + GetDataEventOutcome getDataOutcome = dataService.getData(new GetDataParams(assignOutcome.getTask(), + assignOutcome.getCase(), userService.getSystemUser().getStringId())); + outcomes.add(getDataOutcome); + log.info("finishTask [{}] in case [{}]", task.getTitle(), useCase.getTitle()); + outcomes.add(finishTask(new TaskParams(getDataOutcome.getTask()))); + } catch (TransitionNotExecutableException e) { + log.error("execution of task [{}] in case [{}] failed: ", task.getTitle(), useCase.getTitle(), e); + } + return outcomes; } + /** + * Assigns all provided tasks by provided user. + * + * @param tasks list of tasks to be assigned + * @param actorId id of the assignee of the tasks + * @param params additional parameters for the assign task event + * + * @return list of outcomes of the assign events. The order is the same as the order of the provided list of tasks + * */ @Override - public List<AssignTaskEventOutcome> assignTasks(List<Task> tasks, IUser user, Map<String, String> params) throws TransitionNotExecutableException { + public List<AssignTaskEventOutcome> assignTasks(List<Task> tasks, String actorId, Map<String, String> params) throws TransitionNotExecutableException { List<AssignTaskEventOutcome> outcomes = new ArrayList<>(); for (Task task : tasks) { - outcomes.add(assignTask(task, user, params)); + outcomes.add( + assignTask(TaskParams.with() + .task(task) + .assigneeId(actorId) + .params(params) + .build()) + ); } return outcomes; } + /** + * Assigns the {@link Task} by provided parameters + * + * @param taskParams parameters to determine the Task to be assigned + * <br> + * <b>Required parameters</b> + * <ul> + * <li>taskId or task</li> + * <li>user</li> + * </ul> + * + * @return outcome of the assign event + * */ @Override - public AssignTaskEventOutcome assignTask(String taskId) throws TransitionNotExecutableException { - return assignTask(taskId, new HashMap<>()); + public AssignTaskEventOutcome assignTask(TaskParams taskParams) throws TransitionNotExecutableException { + fillMissingAttributes(taskParams); + throwIfNotEnabled(taskParams.getTask()); + + if (taskParams.getIsTransactional() && !TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<AssignTaskEventOutcome>(null) { + @Override + public AssignTaskEventOutcome call() { + try { + return doAssignTask(taskParams); + } catch (TransitionNotExecutableException e) { + throw new RuntimeException(e); + } + } + }) + .build(); + transaction.begin(); + return (AssignTaskEventOutcome) transaction.getResultOfEvent(); + } else { + return doAssignTask(taskParams); + } } - @Override - public AssignTaskEventOutcome assignTask(String taskId, Map<String, String> params) throws TransitionNotExecutableException { - LoggedUser user = userService.getLoggedOrSystem().transformToLoggedUser(); - return assignTask(user, taskId, params); - } + private AssignTaskEventOutcome doAssignTask(TaskParams taskParams) throws TransitionNotExecutableException { + Task task = taskParams.getTask(); + Case useCase = taskParams.getUseCase(); + String actorId = taskParams.getAssigneeId(); - @Override - public AssignTaskEventOutcome assignTask(LoggedUser loggedUser, String taskId) throws TransitionNotExecutableException { - return assignTask(loggedUser, taskId, new HashMap<>()); - } + Transition transition = useCase.getProcess().getTransition(task.getTransitionId()); - @Override - public AssignTaskEventOutcome assignTask(LoggedUser loggedUser, String taskId, Map<String, String> params) throws TransitionNotExecutableException, TaskNotFoundException { - Optional<Task> taskOptional = taskRepository.findById(taskId); - if (taskOptional.isEmpty()) { - throw new TaskNotFoundException("Could not find task with id [" + taskId + "]"); + List<EventOutcome> outcomes = new ArrayList<>(eventService.runActions(transition.getPreAssignActions(), useCase, + task, transition, taskParams.getParams())); + + if (!outcomes.isEmpty()) { + useCase = workflowService.findOne(task.getCaseId()); + task = findOne(task.getStringId()); } - IUser user = userService.getUserFromLoggedUser(loggedUser); - return assignTask(taskOptional.get(), user, params); - } - @Override - public AssignTaskEventOutcome assignTask(Task task, IUser user) throws TransitionNotExecutableException { - return assignTask(task, user, new HashMap<>()); - } + useCase = evaluateRules(useCase, task, EventType.ASSIGN, EventPhase.PRE); + DoEventTaskOutcome doOutcome = doAssignTaskToUser(actorId, task, transition, useCase); + useCase = doOutcome.getUseCase(); + task = doOutcome.getTask(); - @Override - public AssignTaskEventOutcome assignTask(Task task, IUser user, Map<String, String> params) throws TransitionNotExecutableException { - Case useCase = workflowService.findOne(task.getCaseId()); - Transition transition = useCase.getPetriNet().getTransition(task.getTransitionId()); - List<EventOutcome> outcomes = new ArrayList<>(eventService.runActions(transition.getPreAssignActions(), workflowService.findOne(task.getCaseId()), task, transition, params)); - useCase = workflowService.findOne(task.getCaseId()); - task = findOne(task.getStringId()); - evaluateRules(useCase.getStringId(), task, EventType.ASSIGN, EventPhase.PRE); - useCase = workflowService.findOne(task.getCaseId()); - assignTaskToUser(user, task, useCase.getStringId()); - useCase = workflowService.findOne(task.getCaseId()); - historyService.save(new AssignTaskEventLog(task, useCase, EventPhase.PRE, user)); - outcomes.addAll((eventService.runActions(transition.getPostAssignActions(), workflowService.findOne(task.getCaseId()), task, transition, params))); - useCase = workflowService.findOne(task.getCaseId()); - evaluateRules(useCase.getStringId(), task, EventType.ASSIGN, EventPhase.POST); - useCase = workflowService.findOne(task.getCaseId()); - historyService.save(new AssignTaskEventLog(task, useCase, EventPhase.POST, user)); - - AssignTaskEventOutcome outcome = new AssignTaskEventOutcome(workflowService.findOne(task.getCaseId()), task, outcomes); + historyService.save(new AssignTaskEventLog(task, useCase, EventPhase.PRE, actorId)); + + List<EventOutcome> postEventOutcomes = eventService.runActions(transition.getPostAssignActions(), useCase, task, + transition, taskParams.getParams()); + if (!postEventOutcomes.isEmpty()) { + outcomes.addAll(postEventOutcomes); + useCase = workflowService.findOne(useCase.getStringId()); + } + + useCase = evaluateRules(useCase, task, EventType.ASSIGN, EventPhase.POST); + + historyService.save(new AssignTaskEventLog(task, useCase, EventPhase.POST, actorId)); + + AssignTaskEventOutcome outcome = new AssignTaskEventOutcome(useCase, task, outcomes); addMessageToOutcome(transition, EventType.ASSIGN, outcome); - log.info("[{}]: Task [{}] in case [{}] assigned to [{}]", useCase.getStringId(), task.getTitle(), useCase.getTitle(), user.getSelfOrImpersonated().getEmail()); + log.info("[{}]: Task [{}] in case [{}] assigned to [{}]", useCase.getStringId(), task.getTitle(), useCase.getTitle(), + actorId); return outcome; } - protected Case assignTaskToUser(IUser user, Task task, String useCaseId) throws TransitionNotExecutableException { - Case useCase = workflowService.findOne(useCaseId); - useCase.getPetriNet().initializeArcs(); - Transition transition = useCase.getPetriNet().getTransition(task.getTransitionId()); + private DoEventTaskOutcome doAssignTaskToUser(String actorId, Task task, Transition transition, Case useCase) throws TransitionNotExecutableException { + useCase.getProcess().initializeArcs(); - log.info("[{}]: Assigning task [{}] to user [{}]", useCaseId, task.getTitle(), user.getSelfOrImpersonated().getEmail()); + log.info("[{}]: Assigning task [{}] to actor [{}]", useCase.getStringId(), task.getTitle(), actorId); startExecution(transition, useCase); - task.setUserId(user.getSelfOrImpersonated().getStringId()); + task.setAssigneeId(actorId); task.setLastAssigned(LocalDateTime.now()); - task.setUser(user.getSelfOrImpersonated()); - workflowService.save(useCase); + useCase = workflowService.save(useCase); save(task); - reloadTasks(workflowService.findOne(useCase.getStringId())); - return workflowService.findOne(useCase.getStringId()); - } - @Override - public List<FinishTaskEventOutcome> finishTasks(List<Task> tasks, IUser user) throws TransitionNotExecutableException { - return finishTasks(tasks, user, new HashMap<>()); + boolean anyTaskExecuted = reloadTasks(useCase); + if (anyTaskExecuted) { + useCase = workflowService.findOne(useCase.getStringId()); + } + return new DoEventTaskOutcome(task, useCase); } + /** + * Finishes all provided tasks by provided user. + * + * @param tasks list of tasks to be finished + * @param actorId id of assignee of the tasks + * @param params additional parameters for the finish task event + * + * @return list of outcomes of the finish events. The order is the same as the order of the provided list of tasks + * */ @Override - public List<FinishTaskEventOutcome> finishTasks(List<Task> tasks, IUser user, Map<String, String> params) throws TransitionNotExecutableException { + public List<FinishTaskEventOutcome> finishTasks(List<Task> tasks, String actorId, Map<String, String> params) throws TransitionNotExecutableException { List<FinishTaskEventOutcome> outcomes = new ArrayList<>(); for (Task task : tasks) { - outcomes.add(finishTask(task, user, params)); + outcomes.add( + finishTask(TaskParams.with() + .task(task) + .assigneeId(actorId) + .params(params) + .build()) + ); } return outcomes; } + /** + * Finishes the {@link Task} by provided parameters + * + * @param taskParams parameters to determine the Task to be finished + * <br> + * <b>Required parameters</b> + * <ul> + * <li>taskId or task</li> + * <li>user</li> + * </ul> + * + * @return outcome of the finish event + * */ @Override - public FinishTaskEventOutcome finishTask(String taskId) throws IllegalArgumentException, TransitionNotExecutableException { - return finishTask(taskId, new HashMap<>()); - } - - @Override - public FinishTaskEventOutcome finishTask(String taskId, Map<String, String> params) throws IllegalArgumentException, TransitionNotExecutableException { - LoggedUser user = userService.getLoggedOrSystem().transformToLoggedUser(); - return finishTask(user, taskId, params); + public FinishTaskEventOutcome finishTask(TaskParams taskParams) throws TransitionNotExecutableException { + fillMissingAttributes(taskParams); + + if (taskParams.getIsTransactional() && !TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<FinishTaskEventOutcome>(null) { + @Override + public FinishTaskEventOutcome call() { + try { + return doFinishTask(taskParams); + } catch (TransitionNotExecutableException e) { + throw new RuntimeException(e); + } + } + }) + .build(); + transaction.begin(); + return (FinishTaskEventOutcome) transaction.getResultOfEvent(); + } else { + return doFinishTask(taskParams); + } } - @Override - public FinishTaskEventOutcome finishTask(LoggedUser loggedUser, String taskId) throws IllegalArgumentException, TransitionNotExecutableException { - return finishTask(loggedUser, taskId, new HashMap<>()); - } + private FinishTaskEventOutcome doFinishTask(TaskParams taskParams) throws TransitionNotExecutableException { + Task task = taskParams.getTask(); + Case useCase = taskParams.getUseCase(); + String actorId = taskParams.getAssigneeId(); - @Override - public FinishTaskEventOutcome finishTask(LoggedUser loggedUser, String taskId, Map<String, String> params) throws IllegalArgumentException, TransitionNotExecutableException { - Optional<Task> taskOptional = taskRepository.findById(taskId); - if (taskOptional.isEmpty()) { - throw new IllegalArgumentException("Could not find task with id [" + taskId + "]"); - } - Task task = taskOptional.get(); - IUser user = userService.getUserFromLoggedUser(loggedUser); - - if (task.getUserId() == null) { - throw new IllegalArgumentException("Task with id=" + taskId + " is not assigned to any user."); + if (task.getAssigneeId() == null) { + throw new IllegalArgumentException("Task with id=" + task.getStringId() + " is not assigned to any actor."); } // TODO: 14. 4. 2017 replace with @PreAuthorize - if (!task.getUserId().equals(user.getSelfOrImpersonated().getStringId()) && !loggedUser.isAnonymous()) { - throw new IllegalArgumentException("User that is not assigned tried to finish task"); + if (!task.getAssigneeId().equals(actorId)) { + throw new IllegalArgumentException("Actor that is not assigned tried to finish task"); } - return finishTask(task, user, params); - } + Transition transition = useCase.getProcess().getTransition(task.getTransitionId()); - @Override - public FinishTaskEventOutcome finishTask(Task task, IUser user) throws TransitionNotExecutableException { - return finishTask(task, user, new HashMap<>()); - } + log.info("[{}]: Finishing task [{}] to actor [{}]", useCase.getStringId(), task.getTitle(), actorId); - @Override - public FinishTaskEventOutcome finishTask(Task task, IUser user, Map<String, String> params) throws TransitionNotExecutableException { - Case useCase = workflowService.findOne(task.getCaseId()); - Transition transition = useCase.getPetriNet().getTransition(task.getTransitionId()); + // todo: release/8.0.0 backend validation on finish + List<EventOutcome> outcomes = new ArrayList<>(eventService.runActions(transition.getPreFinishActions(), useCase, + task, transition, taskParams.getParams())); + if (!outcomes.isEmpty()) { + useCase = workflowService.findOne(task.getCaseId()); + task = findOne(task.getStringId()); + } - log.info("[{}]: Finishing task [{}] to user [{}]", useCase.getStringId(), task.getTitle(), user.getSelfOrImpersonated().getEmail()); + useCase = evaluateRules(useCase, task, EventType.FINISH, EventPhase.PRE); + DoEventTaskOutcome doOutcome = doFinishTaskByAssignedUser(task, transition, useCase); + useCase = doOutcome.getUseCase(); + task = doOutcome.getTask(); - validateData(transition, useCase); - List<EventOutcome> outcomes = new ArrayList<>(eventService.runActions(transition.getPreFinishActions(), workflowService.findOne(task.getCaseId()), task, transition, params)); - useCase = workflowService.findOne(task.getCaseId()); - task = findOne(task.getStringId()); - evaluateRules(useCase.getStringId(), task, EventType.FINISH, EventPhase.PRE); - useCase = workflowService.findOne(task.getCaseId()); + historyService.save(new FinishTaskEventLog(task, useCase, EventPhase.PRE, actorId)); - finishExecution(transition, useCase.getStringId()); - task.setLastFinished(LocalDateTime.now()); - task.setFinishedBy(task.getUserId()); - task.setUserId(null); - save(task); - reloadTasks(workflowService.findOne(task.getCaseId())); - useCase = workflowService.findOne(task.getCaseId()); - historyService.save(new FinishTaskEventLog(task, useCase, EventPhase.PRE, user)); - outcomes.addAll(eventService.runActions(transition.getPostFinishActions(), workflowService.findOne(task.getCaseId()), task, transition, params)); - useCase = workflowService.findOne(task.getCaseId()); - evaluateRules(useCase.getStringId(), task, EventType.FINISH, EventPhase.POST); - useCase = workflowService.findOne(task.getCaseId()); - FinishTaskEventOutcome outcome = new FinishTaskEventOutcome(workflowService.findOne(task.getCaseId()), task, outcomes); + List<EventOutcome> postFinishOutcomes = eventService.runActions(transition.getPostFinishActions(), useCase, task, + transition, taskParams.getParams()); + if (!postFinishOutcomes.isEmpty()) { + outcomes.addAll(postFinishOutcomes); + useCase = workflowService.findOne(task.getCaseId()); + } + + useCase = evaluateRules(useCase, task, EventType.FINISH, EventPhase.POST); + + historyService.save(new FinishTaskEventLog(task, useCase, EventPhase.POST, actorId)); + + FinishTaskEventOutcome outcome = new FinishTaskEventOutcome(useCase, task, outcomes); addMessageToOutcome(transition, EventType.FINISH, outcome); - historyService.save(new FinishTaskEventLog(task, useCase, EventPhase.POST, user)); - log.info("[{}]: Task [{}] in case [{}] assigned to [{}] was finished", useCase.getStringId(), task.getTitle(), useCase.getTitle(), user.getSelfOrImpersonated().getEmail()); + log.info("[{}]: Task [{}] in case [{}] assigned to [{}] was finished", useCase.getStringId(), task.getTitle(), + useCase.getTitle(), actorId); return outcome; } - @Override - public List<CancelTaskEventOutcome> cancelTasks(List<Task> tasks, IUser user) { - return cancelTasks(tasks, user, new HashMap<>()); + private DoEventTaskOutcome doFinishTaskByAssignedUser(Task task, Transition transition, Case useCase) { + useCase = finishExecution(transition, useCase); + + task.setLastFinished(LocalDateTime.now()); + task.setFinishedBy(task.getAssigneeId()); + task.setAssigneeId(null); + save(task); + + boolean anyTaskExecuted = reloadTasks(useCase); + if (anyTaskExecuted) { + useCase = workflowService.findOne(useCase.getStringId()); + } + return new DoEventTaskOutcome(task, useCase); } + /** + * Cancels all provided tasks by provided user. + * + * @param tasks list of tasks to be canceled + * @param actorId id of actor by which the task is canceled + * @param params additional parameters for the cancel task event + * + * @return list of outcomes of the cancel events. The order is the same as the order of the provided list of tasks + * */ @Override - public List<CancelTaskEventOutcome> cancelTasks(List<Task> tasks, IUser user, Map<String, String> params) { + public List<CancelTaskEventOutcome> cancelTasks(List<Task> tasks, String actorId, Map<String, String> params) { List<CancelTaskEventOutcome> outcomes = new ArrayList<>(); for (Task task : tasks) { - outcomes.add(cancelTask(task, user, params)); + outcomes.add( + cancelTask(TaskParams.with() + .task(task) + .assigneeId(actorId) + .params(params) + .build()) + ); } return outcomes; } + /** + * Cancels the {@link Task} by provided parameters + * + * @param taskParams parameters to determine the Task to be canceled + * <br> + * <b>Required parameters</b> + * <ul> + * <li>taskId or task</li> + * <li>user</li> + * </ul> + * + * @return outcome of the cancel event + * */ @Override - public CancelTaskEventOutcome cancelTask(LoggedUser loggedUser, String taskId) { - return cancelTask(loggedUser, taskId, new HashMap<>()); + public CancelTaskEventOutcome cancelTask(TaskParams taskParams) { + fillMissingAttributes(taskParams); + + if (taskParams.getIsTransactional() && !TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<CancelTaskEventOutcome>(null) { + @Override + public CancelTaskEventOutcome call() { + return doCancelTask(taskParams); + } + }) + .build(); + transaction.begin(); + return (CancelTaskEventOutcome) transaction.getResultOfEvent(); + } else { + return doCancelTask(taskParams); + } } - @Override - public CancelTaskEventOutcome cancelTask(LoggedUser loggedUser, String taskId, Map<String, String> params) { - Optional<Task> taskOptional = taskRepository.findById(taskId); - if (taskOptional.isEmpty()) { - throw new IllegalArgumentException("Could not find task with id [" + taskId + "]"); + private CancelTaskEventOutcome doCancelTask(TaskParams taskParams) { + Task task = taskParams.getTask(); + String actorId = taskParams.getAssigneeId(); + Case useCase = taskParams.getUseCase(); + + Transition transition = useCase.getProcess().getTransition(task.getTransitionId()); + + log.info("[{}]: Canceling task [{}] to actor [{}]", useCase.getStringId(), task.getTitle(), actorId); + + List<EventOutcome> outcomes = new ArrayList<>(eventService.runActions(transition.getPreCancelActions(), useCase, + task, transition, taskParams.getParams())); + if (!outcomes.isEmpty()) { + useCase = workflowService.findOne(task.getCaseId()); + task = findOne(task.getStringId()); } - IUser user = userService.getUserFromLoggedUser(loggedUser); - return cancelTask(taskOptional.get(), user, params); - } - @Override - public CancelTaskEventOutcome cancelTask(Task task, IUser user) { - return cancelTask(task, user, new HashMap<>()); - } + useCase = evaluateRules(useCase, task, EventType.CANCEL, EventPhase.PRE); + DoEventTaskOutcome doOutcome = doCancelTaskToUser(task, useCase); + useCase = doOutcome.getUseCase(); + task = doOutcome.getTask(); - @Override - public CancelTaskEventOutcome cancelTask(Task task, IUser user, Map<String, String> params) { - Case useCase = workflowService.findOne(task.getCaseId()); - Transition transition = useCase.getPetriNet().getTransition(task.getTransitionId()); + historyService.save(new CancelTaskEventLog(task, useCase, EventPhase.PRE, actorId)); + + List<EventOutcome> postEventOutcomes = eventService.runActions(transition.getPostCancelActions(), useCase, task, + transition, taskParams.getParams()); + if (!postEventOutcomes.isEmpty()) { + outcomes.addAll(postEventOutcomes); + useCase = workflowService.findOne(task.getCaseId()); + } - log.info("[{}]: Canceling task [{}] to user [{}]", useCase.getStringId(), task.getTitle(), user.getSelfOrImpersonated().getEmail()); + useCase = evaluateRules(useCase, task, EventType.CANCEL, EventPhase.POST); - List<EventOutcome> outcomes = new ArrayList<>(eventService.runActions(transition.getPreCancelActions(), workflowService.findOne(task.getCaseId()), task, transition, params)); - useCase = workflowService.findOne(task.getCaseId()); - task = findOne(task.getStringId()); - evaluateRules(useCase.getStringId(), task, EventType.CANCEL, EventPhase.PRE); - useCase = workflowService.findOne(task.getCaseId()); - task = returnTokens(task, useCase.getStringId()); - reloadTasks(workflowService.findOne(task.getCaseId())); - useCase = workflowService.findOne(task.getCaseId()); - historyService.save(new CancelTaskEventLog(task, useCase, EventPhase.PRE, user)); - outcomes.addAll(eventService.runActions(transition.getPostCancelActions(), workflowService.findOne(task.getCaseId()), task, transition, params)); - useCase = workflowService.findOne(task.getCaseId()); - evaluateRules(useCase.getStringId(), task, EventType.CANCEL, EventPhase.POST); - useCase = workflowService.findOne(task.getCaseId()); - CancelTaskEventOutcome outcome = new CancelTaskEventOutcome(workflowService.findOne(task.getCaseId()), task); + CancelTaskEventOutcome outcome = new CancelTaskEventOutcome(useCase, task); outcome.setOutcomes(outcomes); addMessageToOutcome(transition, EventType.CANCEL, outcome); - historyService.save(new CancelTaskEventLog(task, useCase, EventPhase.POST, user)); - log.info("[{}]: Task [{}] in case [{}] assigned to [{}] was cancelled", useCase.getStringId(), task.getTitle(), useCase.getTitle(), user.getSelfOrImpersonated().getEmail()); + historyService.save(new CancelTaskEventLog(task, useCase, EventPhase.POST, actorId)); + + log.info("[{}]: Task [{}] in case [{}] assigned to [{}] was cancelled", useCase.getStringId(), task.getTitle(), + useCase.getTitle(), actorId); return outcome; } - private Task returnTokens(Task task, String useCaseId) { - Case useCase = workflowService.findOne(useCaseId); - PetriNet net = useCase.getPetriNet(); - net.getArcsOfTransition(task.getTransitionId()).stream() - .filter(arc -> arc.getSource() instanceof Place) + private DoEventTaskOutcome doCancelTaskToUser(Task task, Case useCase) { + Process process = useCase.getProcess(); + Case finalUseCase = useCase; + process.getInputArcsOf(task.getTransitionId()).stream() + .filter(arc -> arc.getSource() != null) .forEach(arc -> { - arc.rollbackExecution(useCase.getConsumedTokens().get(arc.getStringId())); - useCase.getConsumedTokens().remove(arc.getStringId()); + arc.rollbackExecution(finalUseCase.getConsumedTokens().get(arc.getStringId())); + finalUseCase.getConsumedTokens().remove(arc.getStringId()); }); workflowService.updateMarking(useCase); - task.setUserId(null); - // TODO: NAE-1848 should this be null? + task.setAssigneeId(null); + // TODO: release/8.0.0 should this be null? task.setLastAssigned(null); + task = save(task); workflowService.save(useCase); - return task; + boolean anyTaskExecuted = reloadTasks(useCase); + if (anyTaskExecuted) { + useCase = workflowService.findOne(useCase.getStringId()); + } + + return new DoEventTaskOutcome(task, useCase); } @Override - public DelegateTaskEventOutcome delegateTask(LoggedUser loggedUser, String delegatedId, String taskId) throws TransitionNotExecutableException { - return delegateTask(loggedUser, delegatedId, taskId, new HashMap<>()); + public DelegateTaskEventOutcome delegateTask(String actorId, String delegatedId, String taskId) throws TransitionNotExecutableException { + return delegateTask(actorId, delegatedId, taskId, new HashMap<>()); } @Override - public DelegateTaskEventOutcome delegateTask(LoggedUser loggedUser, String delegatedId, String taskId, Map<String, String> params) throws TransitionNotExecutableException { - IUser delegatedUser = userService.resolveById(delegatedId); - IUser delegateUser = userService.getUserFromLoggedUser(loggedUser); + public DelegateTaskEventOutcome delegateTask(String actorId, String delegatedId, String taskId, Map<String, String> params) throws TransitionNotExecutableException { + Optional<User> delegatedActorOpt = userService.findById(delegatedId); + if (delegatedActorOpt.isEmpty()) { + throw new IllegalArgumentException(String.format("Delegated actor with id [%s] does not exist.", delegatedId)); + } Optional<Task> taskOptional = taskRepository.findById(taskId); if (taskOptional.isEmpty()) { @@ -400,40 +527,65 @@ public DelegateTaskEventOutcome delegateTask(LoggedUser loggedUser, String deleg Task task = taskOptional.get(); Case useCase = workflowService.findOne(task.getCaseId()); - Transition transition = useCase.getPetriNet().getTransition(task.getTransitionId()); + Transition transition = useCase.getProcess().getTransition(task.getTransitionId()); - log.info("[{}]: Delegating task [{}] to user [{}]", useCase.getStringId(), task.getTitle(), delegatedUser.getEmail()); + log.info("[{}]: Delegating task [{}] to actor [{}]", useCase.getStringId(), task.getTitle(), + delegatedActorOpt.get().getEmail()); - List<EventOutcome> outcomes = new ArrayList<>(eventService.runActions(transition.getPreDelegateActions(), workflowService.findOne(task.getCaseId()), task, transition, params)); - task = findOne(task.getStringId()); - evaluateRules(useCase.getStringId(), task, EventType.DELEGATE, EventPhase.PRE); - delegate(delegatedUser, task, useCase); - historyService.save(new DelegateTaskEventLog(task, useCase, EventPhase.PRE, delegateUser, delegatedUser.getStringId())); - outcomes.addAll(eventService.runActions(transition.getPostDelegateActions(), workflowService.findOne(task.getCaseId()), task, transition, params)); - evaluateRules(useCase.getStringId(), task, EventType.DELEGATE, EventPhase.POST); +// TODO: release/8.0.0 fix +// List<EventOutcome> outcomes = new ArrayList<>(eventService.runActions(transition.getPreDelegateActions(), workflowService.findOne(task.getCaseId()), task, transition, params)); +// task = findOne(task.getStringId()); +// evaluateRules(useCase.getStringId(), task, EventType.DELEGATE, EventPhase.PRE); +// delegate(delegatedUser, task, useCase); +// historyService.save(new DelegateTaskEventLog(task, useCase, EventPhase.PRE, delegateUser, delegatedUser.getStringId())); +// outcomes.addAll(eventService.runActions(transition.getPostDelegateActions(), workflowService.findOne(task.getCaseId()), task, transition, params)); +// evaluateRules(useCase.getStringId(), task, EventType.DELEGATE, EventPhase.POST); reloadTasks(workflowService.findOne(task.getCaseId())); - DelegateTaskEventOutcome outcome = new DelegateTaskEventOutcome(workflowService.findOne(task.getCaseId()), task, outcomes); - addMessageToOutcome(transition, EventType.DELEGATE, outcome); - historyService.save(new DelegateTaskEventLog(task, useCase, EventPhase.POST, delegateUser, delegatedUser.getStringId())); - log.info("Task [{}] in case [{}] assigned to [{}] was delegated to [{}]", task.getTitle(), useCase.getTitle(), delegateUser.getSelfOrImpersonated().getEmail(), delegatedUser.getEmail()); +// DelegateTaskEventOutcome outcome = new DelegateTaskEventOutcome(workflowService.findOne(task.getCaseId()), task, outcomes); +// addMessageToOutcome(transition, EventType.DELEGATE, outcome); +// historyService.save(new DelegateTaskEventLog(task, useCase, EventPhase.POST, delegateUser, delegatedUser.getStringId())); +// log.info("Task [{}] in case [{}] assigned to [{}] was delegated to [{}]", task.getTitle(), useCase.getTitle(), delegateUser.getSelfOrImpersonated().getEmail(), delegatedUser.getEmail()); +// +// return outcome; + return null; + } - return outcome; + private void delegate(User delegatedActor, Task task, Case useCase) throws TransitionNotExecutableException { +// TODO: release/8.0.0 +// if (task.getUserId() != null) { +// task.setAssigneeId(delegated.getStringId()); +// save(task); +// } else { +// assignTaskToUser(delegated, task, useCase.getStringId()); +// } } - protected void delegate(IUser delegated, Task task, Case useCase) throws TransitionNotExecutableException { - if (task.getUserId() != null) { - task.setUserId(delegated.getStringId()); - task.setUser(delegated); - save(task); - } else { - assignTaskToUser(delegated, task, useCase.getStringId()); + private void fillMissingAttributes(TaskParams taskParams) { + if (taskParams.getTask() == null) { + Task task = findOne(taskParams.getTaskId()); + taskParams.setTask(task); + } + if (taskParams.getUseCase() == null) { + Case useCase = workflowService.findOne(taskParams.getTask().getCaseId()); + taskParams.setUseCase(useCase); + } + if (taskParams.getAssigneeId() == null) { + taskParams.setAssigneeId(sessionManagerService.getActiveActorId()); + } + if (taskParams.getIsTransactional() == null) { + taskParams.setIsTransactional(transactionProperties.isTaskEventTransactional()); + } + } + + private void throwIfNotEnabled(@NotNull Task task) { + if (!task.getState().equals(State.ENABLED)) { + throw new IllegalArgumentException("Cannot continue. The task is not active!"); } } - protected Case evaluateRules(String caseId, Task task, EventType eventType, EventPhase eventPhase) { - Case useCase = workflowService.findOne(caseId); + private Case evaluateRules(Case useCase, Task task, EventType eventType, EventPhase eventPhase) { log.info("[{}]: Task [{}] in case [{}] evaluating rules of event {} of phase {}", useCase.getStringId(), task.getTitle(), useCase.getTitle(), eventType.name(), eventPhase.name()); int rulesExecuted = ruleEngine.evaluateRules(useCase, task, TransitionEventFact.of(task, eventType, eventPhase)); if (rulesExecuted == 0) { @@ -443,143 +595,197 @@ protected Case evaluateRules(String caseId, Task task, EventType eventType, Even } /** - * Reloads all unassigned tasks of given case: - * <table border="1"> - * <tr> - * <td></td><td>Task is present</td><td>Task is not present</td> - * </tr> - * <tr> - * <td>Transition executable</td><td>no action</td><td>create task</td> - * </tr> - * <tr> - * <td>Transition not executable</td><td>destroy task</td><td>no action</td> - * </tr> - * </table> + * Updates the {@link State} of all the {@link Task} objects of the provided {@link Case} + * + * @param useCase Case where the tasks exist, which are updated + * + * @return true if at least one auto-trigger Task was executed. */ - @SuppressWarnings("StatementWithEmptyBody") @Override - public void reloadTasks(Case useCase) { + public boolean reloadTasks(Case useCase) { log.info("[{}]: Reloading tasks in [{}]", useCase.getStringId(), useCase.getTitle()); - PetriNet net = useCase.getPetriNet(); - List<Task> tasks; - // create tasks on first reload (create case) - if (useCase.getTasks().isEmpty()) { - tasks = net.getTransitions().values().stream() - .map(transition -> createFromTransition(transition, useCase)) - .collect(Collectors.toList()); + List<String> taskIds = useCase.getTasks().values().stream() + .map(taskPair -> taskPair.getTaskId().toString()) + .collect(Collectors.toList()); + + Optional<Task> autoTriggerTaskOpt = reloadAndSaveTasks((List<Task>) taskRepository.findAllById(taskIds), useCase); + + if (autoTriggerTaskOpt.isPresent()) { + executeTask(autoTriggerTaskOpt.get(), workflowService.findOne(useCase.getStringId())); + return true; } else { - tasks = taskRepository.findAllByCaseId(useCase.getStringId()); + return false; + } + } + + @Override + public boolean isAssigned(Task task) { + if (task == null) { + return false; } - // update tasks state + return task.getAssigneeId() != null; + } + + /** + * Updates {@link State} of the provided tasks, that exist in provided {@link Case}. Only tasks with the changed + * state are updated in database. + * + * @param tasks list of tasks to be updated + * @param useCase Case object where the tasks exist + * + * @return optional auto-trigger task, that is not yet executed. + * */ + private Optional<Task> reloadAndSaveTasks(List<Task> tasks, Case useCase) { Task autoTriggered = null; + Process process = useCase.getProcess(); + List<Task> changedTasks = new ArrayList<>(); for (Task task : tasks) { - Transition transition = net.getTransition(task.getTransitionId()); - if (isExecutable(transition, net)) { - task.setState(State.ENABLED); - if (task.isAutoTriggered()) { - autoTriggered = task; - } - } else { - task.setState(State.DISABLED); + Transition transition = process.getTransition(task.getTransitionId()); + UpdateTaskStateOutcome updateTaskStateOutcome = updateStateOfTask(task, transition, useCase); + if (updateTaskStateOutcome.isMustBeExecuted()) { + autoTriggered = task; + } + if (updateTaskStateOutcome.isWasChanged()) { + changedTasks.add(task); } - save(task); - } - if (autoTriggered != null) { - executeTransition(autoTriggered, workflowService.findOne(useCase.getStringId())); } + save(changedTasks); + + return autoTriggered == null ? Optional.empty() : Optional.of(autoTriggered); } - boolean isExecutable(Transition transition, PetriNet net) { - Collection<Arc> arcsOfTransition = net.getArcsOfTransition(transition); + /** + * For every {@link Transition} in {@link Process} is created {@link Task} and saved into provided {@link Case}. + * Tasks are saved into database by {@link #reloadAndSaveTasks(List, Case)}. UseCase is not saved into database by + * this method. + * + * @param useCase Case object, where the new tasks are saved. It must contain {@link Case#getProcess()} ()} initialized. + * + * @return created tasks and auto-trigger task as optional. Auto-trigger task is within the tasks collection + * */ + @Override + public CreateTasksOutcome createAndSetTasksInCase(Case useCase) { + List<Task> tasks = useCase.getProcess().getTransitions().values().stream() + .map(transition -> createTaskFromTransition(transition, useCase)) + .collect(Collectors.toList()); - if (arcsOfTransition == null) { - return true; - } - // TODO: NAE-1858 is this valid check? what about multiple input arcs from same place? - return arcsOfTransition.stream() - .filter(arc -> arc.getDestination().equals(transition)) // todo: from same source error - .allMatch(Arc::isExecutable); - } + useCase.addTasks(tasks); - void finishExecution(Transition transition, String useCaseId) throws TransitionNotExecutableException { - Case useCase = workflowService.findOne(useCaseId); - log.info("[{}]: Finish execution of task [{}] in case [{}]", useCaseId, transition.getTitle(), useCase.getTitle()); - execute(transition, useCase, arc -> arc.getSource().equals(transition)); - Supplier<Stream<Arc>> arcStreamSupplier = () -> useCase.getPetriNet().getArcsOfTransition(transition.getStringId()).stream(); - arcStreamSupplier.get().filter(arc -> useCase.getConsumedTokens().containsKey(arc.getStringId())).forEach(arc -> useCase.getConsumedTokens().remove(arc.getStringId())); - workflowService.save(useCase); - } + Optional<Task> autoTriggerTaskOpt = reloadAndSaveTasks(tasks, useCase); - public void startExecution(Transition transition, Case useCase) throws TransitionNotExecutableException { - log.info("[{}]: Start execution of {} in case {}", useCase.getStringId(), transition.getTitle(), useCase.getTitle()); - execute(transition, useCase, arc -> arc.getDestination().equals(transition)); + return new CreateTasksOutcome(useCase, tasks, autoTriggerTaskOpt.orElse(null)); } - protected void execute(Transition transition, Case useCase, Predicate<Arc> predicate) throws TransitionNotExecutableException { - Supplier<Stream<Arc>> filteredSupplier = () -> useCase.getPetriNet().getArcsOfTransition(transition.getStringId()).stream().filter(predicate); + /** + * Creates the {@link Task} object by the provided {@link Transition} and {@link Case}. Task is not saved in database + * and Case object. + * + * @param transition transition, from which the Task is created + * @param useCase Case, where the created Task should be later saved + * + * @return created Task + * */ + private Task createTaskFromTransition(Transition transition, Case useCase) { + final Task task = Task.with() + .title(transition.getTitle()) + .processId(useCase.getPetriNetId()) + .caseId(useCase.getId().toString()) + .transitionId(transition.getImportId()) + .properties(transition.getProperties().getMap()) + .processRolePermissions(new AccessPermissions<>(transition.getProcessRolePermissions())) + .icon(transition.getIcon() == null ? useCase.getIcon() : transition.getIcon()) + .immediateDataFields(transition.getImmediateData()) + .assignPolicy(transition.getAssignPolicy()) + .finishPolicy(transition.getFinishPolicy()) + .build(); + for (Trigger trigger : transition.getTriggers()) { + Trigger taskTrigger = trigger.clone(); + task.addTrigger(taskTrigger); - if (!filteredSupplier.get().allMatch(Arc::isExecutable)) { - throw new TransitionNotExecutableException("Not all arcs can be executed task [" + transition.getStringId() + "] in case [" + useCase.getTitle() + "]"); + if (taskTrigger instanceof TimeTrigger) { + TimeTrigger timeTrigger = (TimeTrigger) taskTrigger; + scheduleTaskExecution(task, timeTrigger.getStartDate(), useCase); + } else if (taskTrigger instanceof AutoTrigger) { + task.setAssigneeId(userService.getSystemUser().getStringId()); + } } - filteredSupplier.get().sorted((o1, o2) -> ArcOrderComparator.getInstance().compare(o1, o2)).forEach(arc -> { - if (arc instanceof ResetArc) { - useCase.getConsumedTokens().put(arc.getStringId(), ((Place) arc.getSource()).getTokens()); - } - if (arc.getReference() != null && arc.getSource() instanceof Place) { - useCase.getConsumedTokens().put(arc.getStringId(), arc.getReference().getMultiplicity()); - } - arc.execute(); - }); + return task; + } - workflowService.updateMarking(useCase); + + /** + * Updates the {@link State} of provided {@link Task}. The state depends on {@link #isExecutable(Transition, Case)} + * + * @param task Task, where the state might be updated + * @param transition transition, by which the execution is determined + * @param useCase case, by which the execution is determined + * + * @return boolean value if the state was updated and if the task must be executed + * */ + private UpdateTaskStateOutcome updateStateOfTask(Task task, Transition transition, Case useCase) { + if (isExecutable(transition, useCase)) { + boolean willBeChanged = task.getState() != State.ENABLED; + task.setState(State.ENABLED); + return new UpdateTaskStateOutcome(willBeChanged, task.isAutoTriggered()); + } else { + boolean willBeChanged = task.getState() != State.DISABLED; + task.setState(State.DISABLED); + return new UpdateTaskStateOutcome(willBeChanged, false); + } } - protected List<EventOutcome> executeTransition(Task task, Case useCase) { - log.info("[{}]: executeTransition [{}] in case [{}]", useCase.getStringId(), task.getTransitionId(), useCase.getTitle()); - List<EventOutcome> outcomes = new ArrayList<>(); + private boolean isExecutable(Transition transition, Case useCase) { + List<PTArc> arcsOfTransition = useCase.getProcess().getInputArcsOf(transition.getImportId()); + if (arcsOfTransition == null) { + return true; + } + Map<String, Integer> markingBefore = useCase.getActivePlaces(); + // TODO: NAE-1858 is this valid check? what about multiple input arcs from same place? + // todo: from same source error + // TODO: release/8.0.0 try { - log.info("assignTask [{}] in case [{}]", task.getTitle(), useCase.getTitle()); - outcomes.add(assignTask(task.getStringId())); - log.info("getData [{}] in case [{}]", task.getTitle(), useCase.getTitle()); - outcomes.add(dataService.getData(task.getStringId(), userService.getSystem())); - log.info("finishTask [{}] in case [{}]", task.getTitle(), useCase.getTitle()); - outcomes.add(finishTask(task.getStringId())); - } catch (TransitionNotExecutableException e) { - log.error("execution of task [{}] in case [{}] failed: ", task.getTitle(), useCase.getTitle(), e); + arcsOfTransition.forEach(Arc::execute); + } catch (IllegalMarkingException e) { + useCase.getProcess().setActivePlaces(markingBefore); + return false; } - return outcomes; + return true; } - void validateData(Transition transition, Case useCase) { -// TODO: release/8.0.0 fix validation -// for (Map.Entry<String, DataFieldLogic> entry : transition.getDataSet().entrySet()) { -// if (useCase.getPetriNet().getDataSet().get(entry.getKey()) != null -// && useCase.getPetriNet().getDataSet().get(entry.getKey()).getValidations() != null) { -// validation.valid(useCase.getPetriNet().getDataSet().get(entry.getKey()), useCase.getDataField(entry.getKey())); -// } -// if (!useCase.getDataField(entry.getKey()).isRequired(transition.getImportId())) -// continue; -// if (useCase.getDataField(entry.getKey()).isUndefined(transition.getImportId()) && !entry.getValue().isRequired()) -// continue; -// -// Object value = useCase.getDataSet().get(entry.getKey()).getValue(); -// if (value == null) { -// Field field = useCase.getField(entry.getKey()); -// throw new IllegalArgumentException("Field \"" + field.getName() + "\" has null value"); -// } -// if (value instanceof String && ((String) value).isEmpty()) { -// Field field = useCase.getField(entry.getKey()); -// throw new IllegalArgumentException("Field \"" + field.getName() + "\" has empty value"); -// } -// } + private Case finishExecution(Transition transition, Case useCase) { + log.info("[{}]: Finish execution of task [{}] in case [{}]", useCase.getStringId(), transition.getTitle(), useCase.getTitle()); + // TODO: release/8.0.0 set multiplicity + useCase.getProcess().getOutputArcsOf(transition.getImportId()).forEach(Arc::execute); + workflowService.updateMarking(useCase); + return workflowService.save(useCase); + } + + private void startExecution(Transition transition, Case useCase) throws TransitionNotExecutableException { + log.info("[{}]: Start execution of {} in case {}", useCase.getStringId(), transition.getTitle(), useCase.getTitle()); + + try { + useCase.getProcess().getInputArcsOf(transition.getImportId()).stream() + .sorted((a1, a2) -> ArcOrderComparator.getInstance().compare(a1, a2)) + .forEach(arc -> { + int consumed = arc.getMultiplicity(); + if (arc instanceof ResetArc) { + consumed = arc.getSource().getTokens(); + } + useCase.getConsumedTokens().put(arc.getStringId(), consumed); + arc.execute(); + }); + } catch (IllegalMarkingException e) { + throw new TransitionNotExecutableException("Not all arcs can be executed task [" + transition.getStringId() + "] in case [" + useCase.getTitle() + "]"); + } + workflowService.updateMarking(useCase); } - protected void scheduleTaskExecution(Task task, LocalDateTime time, Case useCase) { + private void scheduleTaskExecution(Task task, LocalDateTime time, Case useCase) { log.info("[{}]: Task {} scheduled to run at {}", useCase.getStringId(), task.getTitle(), time.toString()); scheduler.schedule(() -> { try { - executeTransition(task, useCase); + executeTask(task, useCase); } catch (Exception e) { log.info("[{}]: Scheduled task [{}] of case [{}] could not be executed: {}", useCase.getStringId(), task.getTitle(), useCase.getTitle(), e.toString()); } @@ -597,37 +803,37 @@ public Task findOne(String taskId) { // TODO: release/8.0.0 check usage and delete/replace with current implementation @Override - public Page<Task> getAll(LoggedUser loggedUser, Pageable pageable, Locale locale) { + public Page<Task> getAll(String actorId, Pageable pageable, Locale locale) { List<Task> tasks; - LoggedUser loggedOrImpersonated = loggedUser.getSelfOrImpersonated(); - if (loggedOrImpersonated.getProcessRoles().isEmpty()) { - tasks = new ArrayList<>(); - return new PageImpl<>(tasks, pageable, 0L); - } else { - StringBuilder queryBuilder = new StringBuilder(); - queryBuilder.append("{$or:["); - loggedOrImpersonated.getProcessRoles().forEach(role -> { - queryBuilder.append("{\"roles."); - queryBuilder.append(role); - queryBuilder.append("\":{$exists:true}},"); - }); - if (!loggedOrImpersonated.getProcessRoles().isEmpty()) - queryBuilder.deleteCharAt(queryBuilder.length() - 1); - else - queryBuilder.append("{}"); - queryBuilder.append("]}"); - BasicQuery query = new BasicQuery(queryBuilder.toString()); - query = (BasicQuery) query.with(pageable); - tasks = mongoTemplate.find(query, Task.class); - return loadUsers(new PageImpl<>(tasks, pageable, - mongoTemplate.count(new BasicQuery(queryBuilder.toString(), "{id:1}"), Task.class))); - } - } - - @Override - public Page<Task> search(List<TaskSearchRequest> requests, Pageable pageable, LoggedUser user, Locale locale, Boolean isIntersection) { - com.querydsl.core.types.Predicate searchPredicate = searchService.buildQuery(requests, user, locale, isIntersection); +// if (loggedOrImpersonated.getRoles().isEmpty()) { +// tasks = new ArrayList<>(); +// return new PageImpl<>(tasks, pageable, 0L); +// } else { +// StringBuilder queryBuilder = new StringBuilder(); +// queryBuilder.append("{$or:["); +// loggedOrImpersonated.getRoles().forEach(role -> { +// queryBuilder.append("{\"roles."); +// queryBuilder.append(role); +// queryBuilder.append("\":{$exists:true}},"); +// }); +// if (!loggedOrImpersonated.getRoles().isEmpty()) +// queryBuilder.deleteCharAt(queryBuilder.length() - 1); +// else +// queryBuilder.append("{}"); +// queryBuilder.append("]}"); +// BasicQuery query = new BasicQuery(queryBuilder.toString()); +// query = (BasicQuery) query.with(pageable); +// tasks = mongoTemplate.find(query, Task.class); +// return loadUsers(new PageImpl<>(tasks, pageable, +// mongoTemplate.count(new BasicQuery(queryBuilder.toString(), "{id:1}"), Task.class))); +// } + return Page.empty(); + } + + @Override + public Page<Task> search(List<TaskSearchRequest> requests, Pageable pageable, String actorId, Locale locale, Boolean isIntersection) { + com.querydsl.core.types.Predicate searchPredicate = searchService.buildQuery(requests, actorId, locale, isIntersection); if (searchPredicate != null) { Page<Task> page = taskRepository.findAll(searchPredicate, pageable); page = loadUsers(page); @@ -639,8 +845,8 @@ public Page<Task> search(List<TaskSearchRequest> requests, Pageable pageable, Lo } @Override - public long count(List<TaskSearchRequest> requests, LoggedUser user, Locale locale, Boolean isIntersection) { - com.querydsl.core.types.Predicate searchPredicate = searchService.buildQuery(requests, user, locale, isIntersection); + public long count(List<TaskSearchRequest> requests, String actorId, Locale locale, Boolean isIntersection) { + com.querydsl.core.types.Predicate searchPredicate = searchService.buildQuery(requests, actorId, locale, isIntersection); if (searchPredicate == null) { return 0; } @@ -673,8 +879,16 @@ public List<Task> findAllById(List<String> ids) { } @Override - public Page<Task> findByUser(Pageable pageable, IUser user) { - return loadUsers(taskRepository.findByUserId(pageable, user.getSelfOrImpersonated().getStringId())); + public Page<Task> findByAssignee(Pageable pageable, String actorId) { + return loadUsers(taskRepository.findByAssigneeId(pageable, actorId)); + } + + /** + * todo javadoc + * */ + @Override + public boolean existsByTaskAndAssignee(String taskId, String assigneeId) { + return taskRepository.existsByIdAndAssigneeId(taskId, assigneeId); } @Override @@ -718,45 +932,15 @@ public List<Task> findAllByCase(String caseId) { @Override public Task save(Task task) { task = taskRepository.save(task); - elasticTaskService.index(this.taskMappingService.transform(task)); return task; } @Override public List<Task> save(List<Task> tasks) { tasks = taskRepository.saveAll(tasks); - tasks.forEach(task -> elasticTaskService.index(this.taskMappingService.transform(task))); return tasks; } - @Override - public void resolveUserRef(Case useCase) { - useCase.getTasks().values().forEach(taskPair -> { - Optional<Task> taskOptional = taskRepository.findById(taskPair.getTaskStringId()); - taskOptional.ifPresent(task -> resolveUserRef(task, useCase)); - }); - } - - @Override - public Task resolveUserRef(Task task, Case useCase) { - task.getUsers().clear(); - task.getNegativeViewUsers().clear(); - task.getUserRefs().forEach((id, permission) -> { - UserListField userListField = (UserListField) useCase.getDataSet().get(id); - if (userListField.getValue() == null) { - return; - } - List<String> userIds = getExistingUsers(userListField.getValue().getValue()); - if (userIds != null && userIds.size() != 0 && permission.containsKey(RolePermission.VIEW) && !permission.get(RolePermission.VIEW)) { - task.getNegativeViewUsers().addAll(userIds); - } else if (userIds != null && userIds.size() != 0) { - task.addUsers(new HashSet<>(userIds), permission); - } - }); - task.resolveViewUsers(); - return taskRepository.save(task); - } - private List<String> getExistingUsers(UserListFieldValue userListValue) { if (userListValue == null) { return null; @@ -769,97 +953,35 @@ private List<String> getExistingUsers(UserListFieldValue userListValue) { .collect(Collectors.toList()); } - private Task createFromTransition(Transition transition, Case useCase) { - final Task task = Task.with() - .title(transition.getTitle()) - .processId(useCase.getPetriNetId()) - .caseId(useCase.getId().toString()) - .transitionId(transition.getImportId()) - .layout(transition.getLayout()) - .tags(transition.getTags()) - .caseColor(useCase.getColor()) - .caseTitle(useCase.getTitle()) - .priority(transition.getPriority()) - .icon(transition.getIcon() == null ? useCase.getIcon() : transition.getIcon()) - .immediateDataFields(transition.getImmediateData()) - .assignPolicy(transition.getAssignPolicy()) - .dataFocusPolicy(transition.getDataFocusPolicy()) - .finishPolicy(transition.getFinishPolicy()) - .build(); - transition.getEvents().forEach((type, event) -> task.addEventTitle(type, event.getTitle())); - task.addAssignedUserPolicy(transition.getAssignedUserPolicy()); - for (Trigger trigger : transition.getTriggers()) { - Trigger taskTrigger = trigger.clone(); - task.addTrigger(taskTrigger); - - if (taskTrigger instanceof TimeTrigger) { - TimeTrigger timeTrigger = (TimeTrigger) taskTrigger; - scheduleTaskExecution(task, timeTrigger.getStartDate(), useCase); - } else if (taskTrigger instanceof AutoTrigger) { - task.setUserId(userService.getSystem().getStringId()); - } - } - ProcessRole defaultRole = processRoleService.defaultRole(); - ProcessRole anonymousRole = processRoleService.anonymousRole(); - for (Map.Entry<String, Map<RolePermission, Boolean>> entry : transition.getRoles().entrySet()) { - if (useCase.getEnabledRoles().contains(entry.getKey()) - || defaultRole.getStringId().equals(entry.getKey()) - || anonymousRole.getStringId().equals(entry.getKey())) { - task.addRole(entry.getKey(), entry.getValue()); - } - } - transition.getNegativeViewRoles().forEach(task::addNegativeViewRole); - - for (Map.Entry<String, Map<RolePermission, Boolean>> entry : transition.getUserRefs().entrySet()) { - task.addUserRef(entry.getKey(), entry.getValue()); - } - task.resolveViewRoles(); - task.resolveViewUserRefs(); - - Transaction transaction = useCase.getPetriNet().getTransactionByTransition(transition); - if (transaction != null) { - task.setTransactionId(transaction.getStringId()); - } - - Task savedTask = save(task); - - useCase.addTask(savedTask); - // TODO: release/8.0.0 remove? - workflowService.resolveUserRef(useCase); - - return savedTask; - } - private Page<Task> loadUsers(Page<Task> tasks) { - Map<String, IUser> users = new HashMap<>(); - tasks.forEach(task -> { - if (task.getUserId() != null) { - if (users.containsKey(task.getUserId())) - task.setUser(users.get(task.getUserId())); - else { - task.setUser(userService.resolveById(task.getUserId())); - users.put(task.getUserId(), task.getUser()); - } - } - }); + // TODO: NAE-1969 +// Map<String, IUser> users = new HashMap<>(); +// tasks.forEach(task -> { +// if (task.getUserId() != null) { +// if (users.containsKey(task.getUserId())) +// task.setUser(users.get(task.getUserId())); +// else { +// task.setUser(userService.resolveById(task.getUserId())); +// users.put(task.getUserId(), task.getUser()); +// } +// } +// }); return tasks; } @Override public void delete(List<Task> tasks, Case useCase) { - workflowService.removeTasksFromCase(tasks, useCase); +// TODO: release/8.0.0 +// workflowService.removeTasksFromCase(tasks, useCase); log.info("[{}]: Tasks of case {} are being deleted", useCase.getStringId(), useCase.getTitle()); taskRepository.deleteAll(tasks); - tasks.forEach(t -> elasticTaskService.remove(t.getStringId())); } @Override public void delete(List<Task> tasks, String caseId) { - workflowService.removeTasksFromCase(tasks, caseId); log.info("[{}]: Tasks of case are being deleted", caseId); taskRepository.deleteAll(tasks); - tasks.forEach(t -> elasticTaskService.remove(t.getStringId())); } @Override @@ -873,10 +995,11 @@ public void deleteTasksByPetriNetId(String petriNetId) { } private void setUser(Task task) { - if (task.getUserId() == null) { - return; - } - task.setUser(userService.resolveById(task.getUserId())); +// TODO: release/8.0.0 +// if (task.getUserId() == null) { +// return; +// } +// task.setUser(userService.resolveById(task.getUserId())); } private EventOutcome addMessageToOutcome(Transition transition, EventType type, TaskEventOutcome outcome) { diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java b/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java deleted file mode 100644 index 6fc7e1be2a3..00000000000 --- a/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.netgrif.application.engine.workflow.service; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowAuthorizationService; -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.Arrays; -import java.util.Map; - -@Service -public class WorkflowAuthorizationService extends AbstractAuthorizationService implements IWorkflowAuthorizationService { - - @Autowired - private IWorkflowService workflowService; - - @Autowired - private IPetriNetService petriNetService; - - @Override - public boolean canCallDelete(LoggedUser user, String caseId) { - Case requestedCase = workflowService.findOne(caseId); - Boolean rolePerm = userHasAtLeastOneRolePermission(user.getSelfOrImpersonated().transformToUser(), requestedCase.getPetriNet(), ProcessRolePermission.DELETE); - Boolean userPerm = userHasUserListPermission(user.transformToUser(), requestedCase, ProcessRolePermission.DELETE); - return user.getSelfOrImpersonated().isAdmin() || (userPerm == null ? (rolePerm != null && rolePerm) : userPerm); - } - - @Override - public boolean canCallCreate(LoggedUser user, String netId) { - PetriNet net = petriNetService.getPetriNet(netId); - return user.getSelfOrImpersonated().isAdmin() || userHasAtLeastOneRolePermission(user.transformToUser(), net, ProcessRolePermission.CREATE); - } - - @Override - public Boolean userHasAtLeastOneRolePermission(IUser user, PetriNet net, ProcessRolePermission... permissions) { - Map<ProcessRolePermission, Boolean> aggregatePermissions = getAggregateProcessRolePermissions(user, net.getPermissions()); - - for (ProcessRolePermission permission : permissions) { - if (hasRestrictedPermission(aggregatePermissions.get(permission))) { - return false; - } - } - - return Arrays.stream(permissions).anyMatch(permission -> hasPermission(aggregatePermissions.get(permission))); - } - - @Override - public Boolean userHasUserListPermission(IUser user, Case useCase, ProcessRolePermission... permissions) { - if (useCase.getUserRefs() == null || useCase.getUserRefs().isEmpty()) { - return null; - } - - if (!useCase.getUsers().containsKey(user.getSelfOrImpersonated().getStringId())) { - return null; - } - - Map<ProcessRolePermission, Boolean> userPermissions = useCase.getUsers().get(user.getSelfOrImpersonated().getStringId()); - - for (ProcessRolePermission permission : permissions) { - Boolean perm = userPermissions.get(permission); - if (hasRestrictedPermission(perm)) { - return false; - } - } - return Arrays.stream(permissions).anyMatch(permission -> hasPermission(userPermissions.get(permission))); - } -} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java b/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java index 808e6bc574a..fb428916768 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java @@ -1,34 +1,36 @@ package com.netgrif.application.engine.workflow.service; import com.google.common.collect.Ordering; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseMappingService; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; import com.netgrif.application.engine.history.domain.caseevents.CreateCaseEventLog; import com.netgrif.application.engine.history.domain.caseevents.DeleteCaseEventLog; import com.netgrif.application.engine.history.service.IHistoryService; import com.netgrif.application.engine.importer.model.CaseEventType; -import com.netgrif.application.engine.importer.service.FieldFactory; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.petrinet.domain.Transition; +import com.netgrif.application.engine.petrinet.domain.arcs.Arc; +import com.netgrif.application.engine.petrinet.domain.arcs.ReferenceType; import com.netgrif.application.engine.petrinet.domain.dataset.*; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionRunner; import com.netgrif.application.engine.petrinet.domain.events.EventPhase; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; import com.netgrif.application.engine.rules.domain.facts.CaseCreatedFact; import com.netgrif.application.engine.rules.service.interfaces.IRuleEngine; import com.netgrif.application.engine.security.service.EncryptionService; +import com.netgrif.application.engine.transaction.NaeTransaction; +import com.netgrif.application.engine.transaction.configuration.NaeTransactionProperties; import com.netgrif.application.engine.utils.FullPageRequest; -import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.DataFieldValue; -import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.DeleteCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.*; +import com.netgrif.application.engine.workflow.domain.outcomes.CreateTasksOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.DeleteCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.DeleteCaseParams; import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository; import com.netgrif.application.engine.workflow.service.initializer.DataSetInitializer; import com.netgrif.application.engine.workflow.service.interfaces.IEventService; @@ -36,20 +38,18 @@ import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import com.querydsl.core.types.Predicate; +import groovy.lang.Closure; import lombok.extern.slf4j.Slf4j; import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Lazy; -import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.query.BasicQuery; +import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.data.util.Pair; import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionSynchronizationManager; import java.time.LocalDateTime; import java.util.*; @@ -64,42 +64,27 @@ public class WorkflowService implements IWorkflowService { @Autowired protected CaseRepository repository; - @Autowired - protected MongoTemplate mongoTemplate; - @Autowired protected IPetriNetService petriNetService; @Autowired - protected IProcessRoleService processRoleService; + protected IRoleService roleService; @Autowired protected ITaskService taskService; - @Autowired - protected ApplicationEventPublisher publisher; - @Autowired protected EncryptionService encryptionService; - @Autowired - protected FieldFactory fieldFactory; - @Autowired protected IRuleEngine ruleEngine; @Autowired protected ActionRunner actionsRunner; - @Autowired - protected IUserService userService; - @Autowired protected IInitValueExpressionEvaluator initValueExpressionEvaluator; - @Autowired - protected IElasticCaseMappingService caseMappingService; - @Lazy @Autowired private IEventService eventService; @@ -112,6 +97,15 @@ public class WorkflowService implements IWorkflowService { @Autowired private DataSetInitializer dataSetInitializer; + @Autowired + private ISessionManagerService sessionManagerService; + + @Autowired + private MongoTransactionManager transactionManager; + + @Autowired + private NaeTransactionProperties transactionProperties; + @Autowired public void setElasticCaseService(IElasticCaseService elasticCaseService) { this.elasticCaseService = elasticCaseService; @@ -119,17 +113,12 @@ public void setElasticCaseService(IElasticCaseService elasticCaseService) { @Override public Case save(Case useCase) { - if (useCase.getPetriNet() == null) { + if (useCase.getProcess() == null) { setPetriNet(useCase); } encryptDataSet(useCase); useCase = repository.save(useCase); - try { - useCase.resolveImmediateDataFields(); - elasticCaseService.indexNow(this.caseMappingService.transform(useCase)); - } catch (Exception e) { - log.error("Indexing failed [{}]", useCase.getStringId(), e); - } + return useCase; } @@ -143,14 +132,10 @@ public Case findOne(String caseId) { @Override public Case findOneNoNet(String caseId) { Optional<Case> caseOptional = repository.findById(caseId); - if (caseOptional.isEmpty()) { - throw new IllegalArgumentException("Could not find Case with id [" + caseId + "]"); - } - // TODO: release/8.0.0 get or throw? - return caseOptional.get(); + return caseOptional.orElseThrow(() -> new IllegalArgumentException("Could not find Case with id [" + caseId + "]")); } - protected void initialize(Case useCase) { + private void initialize(Case useCase) { setPetriNet(useCase); decryptDataSet(useCase); useCase.resolveImmediateDataFields(); @@ -190,220 +175,262 @@ public Page<Case> search(Predicate predicate, Pageable pageable) { return page; } + /** + * Create {@link Case} object as {@link CreateCaseEventOutcome} by provided parameters as {@link CreateCaseParams}. + * Created object is saved into database along with the tasks. Any {@link Task}, that should be executed at the + * object creation is executed (auto-trigger tasks). + * + * @param createCaseParams parameters for {@link Case} creation + * <br> + * <b>Required parameters:</b> + * <ul> + * <li>petriNet or petriNetIdentifier or petriNetId</li> + * <li>loggedUser</li> + * </ul> + * + * @return outcome with up to date {@link} Case object containing sub-outcomes as result of triggered events + * */ @Override - public Case resolveUserRef(Case useCase) { - useCase.getUsers().clear(); - useCase.getNegativeViewUsers().clear(); - useCase.getUserRefs().forEach((id, permission) -> resolveUserRefPermissions(useCase, id, permission)); - useCase.resolveViewUsers(); - taskService.resolveUserRef(useCase); - return save(useCase); - } - - private void resolveUserRefPermissions(Case useCase, String userListId, Map<ProcessRolePermission, Boolean> permission) { - List<String> userIds = getExistingUsers((UserListFieldValue) useCase.getDataSet().get(userListId).getRawValue()); - if (userIds != null && !userIds.isEmpty()) { - if (permission.containsKey(ProcessRolePermission.VIEW) && !permission.get(ProcessRolePermission.VIEW)) { - useCase.getNegativeViewUsers().addAll(userIds); - } else { - useCase.addUsers(new HashSet<>(userIds), permission); - } + public CreateCaseEventOutcome createCase(CreateCaseParams createCaseParams) { + fillMissingAttributes(createCaseParams); + + if (createCaseParams.getIsTransactional() && !TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<CreateCaseEventOutcome>(null) { + @Override + public CreateCaseEventOutcome call() { + return doCreateCase(createCaseParams); + } + }) + .build(); + transaction.begin(); + return (CreateCaseEventOutcome) transaction.getResultOfEvent(); + } else { + return doCreateCase(createCaseParams); } } - private List<String> getExistingUsers(UserListFieldValue userListValue) { - if (userListValue == null) { - return null; - } - // TODO: release/8.0.0 fix null set as user value - // TODO: release/8.0.0 .filter(id -> userService.resolveById(id, false) != null) - return userListValue.getUserValues().stream() - .filter(Objects::nonNull) - .map(UserFieldValue::getId) - .filter(id -> id != null && userService.existsById(id)) - .collect(Collectors.toList()); - } + private CreateCaseEventOutcome doCreateCase(CreateCaseParams createCaseParams) { + Case useCase = createCaseObject(createCaseParams); + CreateTasksOutcome createTasksOutcome = taskService.createAndSetTasksInCase(useCase); + dataSetInitializer.populateDataSet(useCase, createCaseParams.getParams()); - @Override - public CreateCaseEventOutcome createCase(String netId, String title, String color, LoggedUser user, Locale locale, Map<String, String> params) { - if (locale == null) { - locale = LocaleContextHolder.getLocale(); + Process process = createCaseParams.getProcess(); + roleService.resolveCaseRolesOnCase(useCase, useCase.getProcess().getCaseRolePermissions(), false); + for (Task task : createTasksOutcome.getTasks()) { + Transition transition = process.getTransition(task.getTransitionId()); + roleService.resolveCaseRolesOnTask(useCase, task, transition.getCaseRolePermissions(), false, true); } - if (title == null) { - return this.createCase(netId, resolveDefaultCaseTitle(netId, locale, params), color, user, params); - } - return this.createCase(netId, title, color, user, params); - } + save(useCase); // must be after tasks creation for effectivity reasons - @Override - public CreateCaseEventOutcome createCase(String netId, String title, String color, LoggedUser user, Locale locale) { - return this.createCase(netId, title, color, user, locale, new HashMap<>()); - } - - @Override - public CreateCaseEventOutcome createCase(String netId, String title, String color, LoggedUser user, Map<String, String> params) { - return createCase(netId, (u) -> title, color, user, params); - } + CreateCaseEventOutcome outcome = new CreateCaseEventOutcome(); - @Override - public CreateCaseEventOutcome createCase(String netId, String title, String color, LoggedUser user) { - return this.createCase(netId, (u) -> title, color, user); - } + // todo: release/8.0.0 pre actions should be run before the actual case creation? At this moment the case already exists in DB + outcome.addOutcomes(eventService.runActions(process.getPreCreateActions(), null, Optional.empty(), + createCaseParams.getParams())); - @Override - public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user, Locale locale, Map<String, String> params) { - PetriNet net = petriNetService.getNewestVersionByIdentifier(identifier); - if (net == null) { - throw new IllegalArgumentException("Petri net with identifier [" + identifier + "] does not exist."); + // todo: release/8.0.0 should ruleEngine have useCase at this stage of execution? + int rulesExecuted = ruleEngine.evaluateRules(useCase, new CaseCreatedFact(useCase.getStringId(), EventPhase.PRE)); + if (rulesExecuted > 0) { + useCase = save(useCase); } - return this.createCase(net.getStringId(), title != null && !title.equals("") ? title : net.getDefaultCaseName().getTranslation(locale), color, user, params); - } - - @Override - public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user, Locale locale) { - return this.createCaseByIdentifier(identifier, title, color, user, locale, new HashMap<>()); - } - @Override - public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user, Map<String, String> params) { - PetriNet net = petriNetService.getNewestVersionByIdentifier(identifier); - if (net == null) { - throw new IllegalArgumentException("Petri net with identifier [" + identifier + "] does not exist."); - } - return this.createCase(net.getStringId(), title, color, user, params); - } + historyService.save(new CreateCaseEventLog(useCase, EventPhase.PRE)); - @Override - public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user) { - PetriNet net = petriNetService.getNewestVersionByIdentifier(identifier); - if (net == null) { - throw new IllegalArgumentException("Petri net with identifier [" + identifier + "] does not exist."); + if (createTasksOutcome.getAutoTriggerTask() != null) { + taskService.executeTask(createTasksOutcome.getAutoTriggerTask(), useCase); + useCase = findOne(useCase.getStringId()); } - return this.createCase(net.getStringId(), title, color, user); - } - public CreateCaseEventOutcome createCase(String netId, Function<Case, String> makeTitle, String color, LoggedUser user) { - return this.createCase(netId, makeTitle, color, user, new HashMap<>()); - } + // TODO release/8.0.0 resolving init of taskRefs is going to be done differently + // resolveTaskRefs(useCase); - public CreateCaseEventOutcome createCase(String netId, Function<Case, String> makeTitle, String color, LoggedUser user, Map<String, String> params) { - LoggedUser loggedOrImpersonated = user.getSelfOrImpersonated(); - PetriNet petriNet = petriNetService.clone(new ObjectId(netId)); - int rulesExecuted; - Case useCase = new Case(petriNet); - dataSetInitializer.populateDataSet(useCase, params); - useCase.setColor(color); - useCase.setAuthor(loggedOrImpersonated.transformToAuthor()); - useCase.setCreationDate(LocalDateTime.now()); - useCase.setTitle(makeTitle.apply(useCase)); - // TODO: release/7.0.0 6.2.5 - // TODO: release/8.0.0 useCase.setUriNodeId(petriNet.getUriNodeId()); -// UriNode uriNode = uriService.getOrCreate(petriNet, UriContentType.CASE); -// useCase.setUriNodeId(uriNode.getId()); - - CreateCaseEventOutcome outcome = new CreateCaseEventOutcome(); - outcome.addOutcomes(eventService.runActions(petriNet.getPreCreateActions(), null, Optional.empty(), params)); - rulesExecuted = ruleEngine.evaluateRules(useCase, new CaseCreatedFact(useCase.getStringId(), EventPhase.PRE)); - if (rulesExecuted > 0) { - useCase = save(useCase); + List<EventOutcome> eventPostOutcomes = eventService.runActions(process.getPostCreateActions(), useCase, Optional.empty(), + createCaseParams.getParams()); + if (!eventPostOutcomes.isEmpty()) { + outcome.addOutcomes(eventPostOutcomes); + useCase = findOne(useCase.getStringId()); } - historyService.save(new CreateCaseEventLog(useCase, EventPhase.PRE)); - log.info("[{}]: Case {} created", useCase.getStringId(), useCase.getTitle()); - - useCase.getPetriNet().initializeArcs(useCase.getDataSet()); - taskService.reloadTasks(useCase); - useCase = findOne(useCase.getStringId()); - resolveTaskRefs(useCase); - - useCase = findOne(useCase.getStringId()); - outcome.addOutcomes(eventService.runActions(petriNet.getPostCreateActions(), useCase, Optional.empty(), params)); - useCase = findOne(useCase.getStringId()); rulesExecuted = ruleEngine.evaluateRules(useCase, new CaseCreatedFact(useCase.getStringId(), EventPhase.POST)); if (rulesExecuted > 0) { useCase = save(useCase); } historyService.save(new CreateCaseEventLog(useCase, EventPhase.POST)); + + log.info("[{}]: Case {} was created by actor {}", useCase.getStringId(), useCase.getTitle(), createCaseParams.getAuthorId()); + outcome.setCase(useCase); - addMessageToOutcome(petriNet, CaseEventType.CREATE, outcome); + addMessageToOutcome(process, CaseEventType.CREATE, outcome); return outcome; } - protected Function<Case, String> resolveDefaultCaseTitle(String netId, Locale locale, Map<String, String> params) { - PetriNet petriNet = petriNetService.clone(new ObjectId(netId)); + /** + * Creates pure {@link Case} object without any {@link Task} object initialized. + * + * @param createCaseParams parameters for object creation + * + * @return created {@link Case} object + * */ + private Case createCaseObject(CreateCaseParams createCaseParams) { + Case useCase = new Case(createCaseParams.getProcess()); + useCase.setAuthorId(createCaseParams.getAuthorId()); + useCase.setCreationDate(LocalDateTime.now()); + useCase.setTitle(createCaseParams.getMakeTitle().apply(useCase)); + useCase.setUriNodeId(createCaseParams.getProcess().getUriNodeId()); + + useCase.getProcess().initializeArcs(); + + return useCase; + } + + private void fillMissingAttributes(CreateCaseParams createCaseParams) throws IllegalArgumentException { + if (createCaseParams.getIsTransactional() == null) { + createCaseParams.setIsTransactional(transactionProperties.isCreateCaseTransactional()); + } + if (createCaseParams.getProcess() == null) { + Process process; + if (createCaseParams.getProcessId() != null) { + process = petriNetService.get(new ObjectId(createCaseParams.getProcessId())).clone(); + } else if (createCaseParams.getProcessIdentifier() != null) { + Process originalProcess = petriNetService.getNewestVersionByIdentifier(createCaseParams.getProcessIdentifier()); + if (originalProcess == null) { + throw new IllegalArgumentException(String.format("Could not find the Process [%s] for the Case creation.", + createCaseParams.getProcessIdentifier())); + } + process = petriNetService.getNewestVersionByIdentifier(createCaseParams.getProcessIdentifier()).clone(); + } else { + throw new IllegalArgumentException("Could not find the Process for the Case from provided inputs on case creation."); + } + createCaseParams.setProcess(process); + } + if (createCaseParams.getMakeTitle() == null && createCaseParams.getProcess() != null) { + createCaseParams.setMakeTitle(resolveDefaultCaseTitle(createCaseParams)); + } + } + + private Function<Case, String> resolveDefaultCaseTitle(CreateCaseParams createCaseParams) { + Locale locale = createCaseParams.getLocale(); + Process process = createCaseParams.getProcess(); Function<Case, String> makeTitle; - if (petriNet.hasDynamicCaseName()) { - makeTitle = (u) -> initValueExpressionEvaluator.evaluateCaseName(u, petriNet.getDefaultCaseNameExpression(), params).getTranslation(locale); + if (process.getDefaultCaseName().isDynamic()) { + makeTitle = (u) -> initValueExpressionEvaluator.evaluate(u, process.getDefaultCaseName().getExpression(locale), + createCaseParams.getParams()); + } else if (process.hasDefaultCaseName()) { + makeTitle = (u) -> process.getDefaultCaseName().getTranslation(locale); } else { - makeTitle = (u) -> petriNet.getDefaultCaseName().getTranslation(locale); + makeTitle = (u) -> null; } return makeTitle; } @Override public Page<Case> findAllByAuthor(String authorId, String petriNet, Pageable pageable) { - String queryString = "{author.id:" + authorId + ", petriNet:{$ref:\"petriNet\",$id:{$oid:\"" + petriNet + "\"}}}"; - BasicQuery query = new BasicQuery(queryString); - query = (BasicQuery) query.with(pageable); -// TODO: release/8.0.0 remove mongoTemplates from project - List<Case> cases = mongoTemplate.find(query, Case.class); + Predicate query = QCase.case$.authorId.eq(authorId).and(QCase.case$.petriNetId.eq(petriNet)); + Page<Case> cases = repository.findAll(query, pageable); cases.forEach(this::initialize); - return new PageImpl<>(cases, pageable, mongoTemplate.count(new BasicQuery(queryString, "{id:1}"), Case.class)); - } - + return cases; + } + + /** + * Deletes the {@link Case} object from database by provided parameters as {@link DeleteCaseParams} + * + * @param deleteCaseParams parameters to determine the object to be deleted + * <br> + * <b>Required parameters</b> + * <ul> + * <li>useCaseId or useCase</li> + * </ul> + * + * @return outcome with the removed {@link Case} object and sub-outcomes as result of triggered events + * */ @Override - public DeleteCaseEventOutcome deleteCase(String caseId) { - return deleteCase(caseId, new HashMap<>()); + public DeleteCaseEventOutcome deleteCase(DeleteCaseParams deleteCaseParams) { + fillMissingAttributes(deleteCaseParams); + + if (deleteCaseParams.getIsTransactional() && !TransactionSynchronizationManager.isSynchronizationActive()) { + NaeTransaction transaction = NaeTransaction.builder() + .transactionManager(transactionManager) + .event(new Closure<DeleteCaseEventOutcome>(null) { + @Override + public DeleteCaseEventOutcome call() { + return doDeleteCase(deleteCaseParams); + } + }) + .build(); + transaction.begin(); + return (DeleteCaseEventOutcome) transaction.getResultOfEvent(); + } else { + return doDeleteCase(deleteCaseParams); + } } - @Override - public DeleteCaseEventOutcome deleteCase(String caseId, Map<String, String> params) { - Case useCase = findOne(caseId); - return deleteCase(useCase, params); - } + private DeleteCaseEventOutcome doDeleteCase(DeleteCaseParams deleteCaseParams) { + Case useCase = deleteCaseParams.getUseCase(); + + List<EventOutcome> preEventOutcomes = eventService.runActions(useCase.getProcess().getPreDeleteActions(), + useCase, Optional.empty(), deleteCaseParams.getParams()); - @Override - public DeleteCaseEventOutcome deleteCase(Case useCase, Map<String, String> params) { - DeleteCaseEventOutcome outcome = new DeleteCaseEventOutcome(useCase, eventService.runActions(useCase.getPetriNet().getPreDeleteActions(), useCase, Optional.empty(), params)); historyService.save(new DeleteCaseEventLog(useCase, EventPhase.PRE)); - log.info("[{}]: User [{}] is deleting case {}", useCase.getStringId(), userService.getLoggedOrSystem().getStringId(), useCase.getTitle()); + log.info("[{}]: Actor [{}] is deleting case {}", useCase.getStringId(), sessionManagerService.getActiveActorId(), + useCase.getTitle()); + + roleService.removeAllByCase(useCase.getStringId()); taskService.deleteTasksByCase(useCase.getStringId()); repository.delete(useCase); - outcome.addOutcomes(eventService.runActions(useCase.getPetriNet().getPostDeleteActions(), null, Optional.empty(), params)); - addMessageToOutcome(useCase.getPetriNet(), CaseEventType.DELETE, outcome); + DeleteCaseEventOutcome outcome = new DeleteCaseEventOutcome(useCase, preEventOutcomes); + outcome.addOutcomes(eventService.runActions(useCase.getProcess().getPostDeleteActions(), null, + Optional.empty(), deleteCaseParams.getParams())); + addMessageToOutcome(useCase.getProcess(), CaseEventType.DELETE, outcome); + historyService.save(new DeleteCaseEventLog(useCase, EventPhase.POST)); + return outcome; } - @Override - public DeleteCaseEventOutcome deleteCase(Case useCase) { - return deleteCase(useCase, new HashMap<>()); + private void fillMissingAttributes(DeleteCaseParams deleteCaseParams) throws IllegalArgumentException { + if (deleteCaseParams.getUseCase() == null) { + if (deleteCaseParams.getUseCaseId() != null) { + deleteCaseParams.setUseCase(findOne(deleteCaseParams.getUseCaseId())); + } else { + throw new IllegalArgumentException("At least case id must be provided on case removal."); + } + } + if (deleteCaseParams.getIsTransactional() == null) { + deleteCaseParams.setIsTransactional(transactionProperties.isDeleteCaseTransactional()); + } } @Override - public void deleteInstancesOfPetriNet(PetriNet net) { - log.info("[{}]: User {} is deleting all cases and tasks of Petri net {} version {}", net.getStringId(), userService.getLoggedOrSystem().getStringId(), net.getIdentifier(), net.getVersion().toString()); + public void deleteInstancesOfPetriNet(Process net) { + log.info("[{}]: Actor {} is deleting all cases and tasks of Petri net {} version {}", net.getStringId(), + sessionManagerService.getActiveActorId(), net.getIdentifier(), net.getVersion().toString()); taskService.deleteTasksByPetriNetId(net.getStringId()); CaseSearchRequest request = new CaseSearchRequest(); CaseSearchRequest.PetriNet netRequest = new CaseSearchRequest.PetriNet(); netRequest.processId = net.getStringId(); request.process = Collections.singletonList(netRequest); - long countCases = elasticCaseService.count(Collections.singletonList(request), userService.getLoggedOrSystem().transformToLoggedUser(), Locale.getDefault(), false); - log.info("[{}]: User {} is deleting {} cases of Petri net {} version {}", net.getStringId(), userService.getLoggedOrSystem().getStringId(), countCases, net.getIdentifier(), net.getVersion().toString()); + long countCases = elasticCaseService.count(Collections.singletonList(request), sessionManagerService.getActiveActorId(), + Locale.getDefault(), false); + log.info("[{}]: Actor [{}] is deleting {} cases of Petri net {} version {}", net.getStringId(), + sessionManagerService.getActiveActorId(), countCases, net.getIdentifier(), + net.getVersion().toString()); + // todo: release/8.0.0 page.unpaged? long pageCount = (countCases / 100) + 1; LongStream.range(0, pageCount) .forEach(i -> elasticCaseService.search( Collections.singletonList(request), - userService.getLoggedOrSystem().transformToLoggedUser(), + sessionManagerService.getActiveActorId(), PageRequest.of((int) i, 100), Locale.getDefault(), false) .getContent() - .forEach(this::deleteCase)); + .forEach(useCase -> deleteCase(new DeleteCaseParams(useCase)))); } @Override @@ -412,34 +439,15 @@ public DeleteCaseEventOutcome deleteSubtreeRootedAt(String subtreeRootCaseId) { if (subtreeRoot.getImmediateDataFields().contains("treeChildCases")) { ((List<String>) subtreeRoot.getDataSet().get("treeChildCases").getValue()).forEach(this::deleteSubtreeRootedAt); } - return deleteCase(subtreeRootCaseId); + return deleteCase(new DeleteCaseParams(subtreeRoot)); } @Override public void updateMarking(Case useCase) { - PetriNet net = useCase.getPetriNet(); + Process net = useCase.getProcess(); useCase.setActivePlaces(net.getActivePlaces()); } - @Override - public void removeTasksFromCase(List<Task> tasks, String caseId) { - Optional<Case> caseOptional = repository.findById(caseId); - if (caseOptional.isEmpty()) { - throw new IllegalArgumentException("Could not find case with id [" + caseId + "]"); - } - Case useCase = caseOptional.get(); - removeTasksFromCase(tasks, useCase); - } - - @Override - public void removeTasksFromCase(List<Task> tasks, Case useCase) { - if (tasks == null || tasks.isEmpty()) { - return; - } - useCase.removeTasks(tasks); - save(useCase); - } - @Override public Case decrypt(Case useCase) { decryptDataSet(useCase); @@ -471,21 +479,24 @@ public Map<String, I18nString> listToMap(List<Case> cases) { return options; } - private void resolveTaskRefs(Case useCase) { - useCase.getPetriNet().getDataSet().values().stream().filter(f -> f instanceof TaskField).map(TaskField.class::cast).forEach(field -> { - if (field.getDefaultValue() != null && !field.getDefaultValue().isEmpty() && useCase.getDataSet().get(field.getStringId()).getValue() != null && - useCase.getDataSet().get(field.getStringId()).getRawValue().equals(field.getDefaultValue())) { - TaskField taskRef = (TaskField) useCase.getDataSet().get(field.getStringId()); - taskRef.setRawValue(new ArrayList<>()); - field.getDefaultValue().forEach(transitionId -> { - if (!useCase.getTasks().containsKey(transitionId)) { - return; + private Case resolveTaskRefs(Case useCase, Map<String, String> params) { + // TODO: release/8.0.0 + Case finalUseCase = findOne(useCase.getStringId()); + useCase.getDataSet().getFields().values().stream() + .filter(field -> field instanceof TaskField && field.getDefaultValue() != null) + .forEach(field -> { + if (field.getDefaultValue().isDynamic()) { + dataSetInitializer.initializeValue(finalUseCase, field, params); + } else { + List<String> defaultValue = ((TaskField) field).getDefaultValue().getDefaultValue(); + ((TaskField) field).setRawValue( + defaultValue.stream() + .map(useCase::getTaskStringId) + .collect(Collectors.toList()) + ); } - taskRef.getRawValue().add(useCase.getTasks().get(transitionId).getTaskStringId()); }); - } - }); - save(useCase); + return save(useCase); } // TODO: release/8.0.0 getData? @@ -516,7 +527,7 @@ private void applyCryptoMethodOnDataSet(Case useCase, Function<Pair<String, Stri } private Map<Field<?>, String> getEncryptedDataSet(Case useCase) { - PetriNet net = useCase.getPetriNet(); + Process net = useCase.getProcess(); Map<Field<?>, String> encryptedDataSet = new HashMap<>(); for (Map.Entry<String, Field<?>> entry : net.getDataSet().entrySet()) { @@ -530,16 +541,42 @@ private Map<Field<?>, String> getEncryptedDataSet(Case useCase) { } private void setPetriNet(Case useCase) { - PetriNet model = useCase.getPetriNet(); + Process model = useCase.getProcess(); if (model == null) { model = petriNetService.clone(useCase.getPetriNetObjectId()); - useCase.setPetriNet(model); + useCase.setProcess(model); } model.initializeTokens(useCase.getActivePlaces()); - model.initializeArcs(useCase.getDataSet()); + resolveArcsWeight(useCase); + } + + private void resolveArcsWeight(Case useCase) { + useCase.getProcess().getArcs().values().forEach(arcCollection -> { + arcCollection.getInput().forEach(arc -> this.resolveWeight(arc, useCase)); + arcCollection.getOutput().forEach(arc -> this.resolveWeight(arc, useCase)); + }); + } + + private void resolveWeight(Arc<?, ?> arc, Case useCase) { + int weight; + if (arc.getMultiplicityExpression().isDynamic()) { + String definition = arc.getMultiplicityExpression().getDefinition(); + ReferenceType referenceType = arc.getMultiplicityExpression().getReferenceType(); + if (referenceType == ReferenceType.PLACE) { + weight = useCase.getProcess().getPlace(definition).getTokens(); + } else if (referenceType == ReferenceType.DATA_VARIABLE) { + weight = ((Number) useCase.getDataSet().get(definition).getRawValue()).intValue(); + } else { + // TODO: release/8.0.0 evaluate expression + weight = 2; + } + } else { + weight = arc.getMultiplicityExpression().getDefaultValue(); + } + arc.setMultiplicity(weight); } - private EventOutcome addMessageToOutcome(PetriNet net, CaseEventType type, EventOutcome outcome) { + private EventOutcome addMessageToOutcome(Process net, CaseEventType type, EventOutcome outcome) { if (net.getCaseEvents().containsKey(type)) { outcome.setMessage(net.getCaseEvents().get(type).getMessage()); } diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/factory/ActorFactory.java b/src/main/java/com/netgrif/application/engine/workflow/service/factory/ActorFactory.java new file mode 100644 index 00000000000..14a849c748e --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/service/factory/ActorFactory.java @@ -0,0 +1,22 @@ +package com.netgrif.application.engine.workflow.service.factory; + +import com.netgrif.application.engine.authorization.domain.Actor; +import com.netgrif.application.engine.authorization.service.ActorTypeRegistry; +import com.netgrif.application.engine.workflow.service.SystemCaseFactoryRegistry; + +import javax.annotation.PostConstruct; + +public abstract class ActorFactory<T extends Actor> extends SystemCaseFactory<T>{ + + protected final ActorTypeRegistry actorTypeRegistry; + + public ActorFactory(SystemCaseFactoryRegistry factoryRegistry, ActorTypeRegistry actorTypeRegistry) { + super(factoryRegistry); + this.actorTypeRegistry = actorTypeRegistry; + } + + // todo javadoc + @PostConstruct + protected abstract void registerType(); + +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/factory/GroupFactory.java b/src/main/java/com/netgrif/application/engine/workflow/service/factory/GroupFactory.java new file mode 100644 index 00000000000..508da6804cd --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/service/factory/GroupFactory.java @@ -0,0 +1,31 @@ +package com.netgrif.application.engine.workflow.service.factory; + +import com.netgrif.application.engine.authorization.domain.Group; +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.authorization.service.ActorTypeRegistry; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.service.SystemCaseFactoryRegistry; +import org.springframework.stereotype.Service; + +@Service +public class GroupFactory extends ActorFactory<Group> { + + public GroupFactory(SystemCaseFactoryRegistry factoryRegistry, ActorTypeRegistry actorTypeRegistry) { + super(factoryRegistry, actorTypeRegistry); + } + + @Override + public Group createObject(Case groupCase) { + return new Group(groupCase); + } + + @Override + protected void registerFactory() { + factoryRegistry.registerFactory(GroupConstants.PROCESS_IDENTIFIER, this); + } + + @Override + protected void registerType() { + actorTypeRegistry.registerActorType(GroupConstants.PROCESS_IDENTIFIER, Group.class); + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/factory/IdentityFactory.java b/src/main/java/com/netgrif/application/engine/workflow/service/factory/IdentityFactory.java new file mode 100644 index 00000000000..5b88d9bfec9 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/service/factory/IdentityFactory.java @@ -0,0 +1,25 @@ +package com.netgrif.application.engine.workflow.service.factory; + +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.constants.IdentityConstants; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.service.SystemCaseFactoryRegistry; +import org.springframework.stereotype.Service; + +@Service +public class IdentityFactory extends SystemCaseFactory<Identity> { + + public IdentityFactory(SystemCaseFactoryRegistry factoryRegistry) { + super(factoryRegistry); + } + + @Override + public Identity createObject(Case identityCase) { + return new Identity(identityCase); + } + + @Override + protected void registerFactory() { + factoryRegistry.registerFactory(IdentityConstants.PROCESS_IDENTIFIER, this); + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/factory/SystemCaseFactory.java b/src/main/java/com/netgrif/application/engine/workflow/service/factory/SystemCaseFactory.java new file mode 100644 index 00000000000..810fb15eefb --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/service/factory/SystemCaseFactory.java @@ -0,0 +1,26 @@ +package com.netgrif.application.engine.workflow.service.factory; + +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.SystemCase; +import com.netgrif.application.engine.workflow.service.SystemCaseFactoryRegistry; +import lombok.RequiredArgsConstructor; + +import javax.annotation.PostConstruct; + +@RequiredArgsConstructor +public abstract class SystemCaseFactory<T extends SystemCase> { + + protected final SystemCaseFactoryRegistry factoryRegistry; + + /** + * todo javadoc + * */ + public abstract T createObject(Case systemCase); + + /** + * todo javadoc + * */ + @PostConstruct + protected abstract void registerFactory(); + +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/factory/UserFactory.java b/src/main/java/com/netgrif/application/engine/workflow/service/factory/UserFactory.java new file mode 100644 index 00000000000..85b247c3f83 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/service/factory/UserFactory.java @@ -0,0 +1,31 @@ +package com.netgrif.application.engine.workflow.service.factory; + +import com.netgrif.application.engine.authorization.domain.User; +import com.netgrif.application.engine.authorization.domain.constants.UserConstants; +import com.netgrif.application.engine.authorization.service.ActorTypeRegistry; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.service.SystemCaseFactoryRegistry; +import org.springframework.stereotype.Service; + +@Service +public class UserFactory extends ActorFactory<User> { + + public UserFactory(SystemCaseFactoryRegistry factoryRegistry, ActorTypeRegistry actorTypeRegistry) { + super(factoryRegistry, actorTypeRegistry); + } + + @Override + public User createObject(Case userCase) { + return new User(userCase); + } + + @Override + protected void registerFactory() { + factoryRegistry.registerFactory(UserConstants.PROCESS_IDENTIFIER, this); + } + + @Override + protected void registerType() { + actorTypeRegistry.registerActorType(UserConstants.PROCESS_IDENTIFIER, User.class); + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/initializer/DataSetInitializer.java b/src/main/java/com/netgrif/application/engine/workflow/service/initializer/DataSetInitializer.java index 8cb962b9ab5..e295c78d951 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/initializer/DataSetInitializer.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/initializer/DataSetInitializer.java @@ -4,13 +4,14 @@ import com.netgrif.application.engine.petrinet.domain.dataset.ChoiceField; import com.netgrif.application.engine.petrinet.domain.dataset.Field; import com.netgrif.application.engine.petrinet.domain.dataset.MapOptionsField; +import com.netgrif.application.engine.petrinet.domain.dataset.TaskField; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.service.interfaces.IInitValueExpressionEvaluator; import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.Arrays; import java.util.Map; +import java.util.stream.Collectors; @Component public class DataSetInitializer { @@ -22,42 +23,45 @@ public DataSetInitializer(IInitValueExpressionEvaluator initValueExpressionEvalu } public void populateDataSet(Case useCase, Map<String, String> params) { - ArrayList<Field<?>> dynamicValueFields = new ArrayList<>(); - ArrayList<ChoiceField<?>> dynamicChoiceFields = new ArrayList<>(); - ArrayList<MapOptionsField<I18nString, ?>> dynamicOptionFields = new ArrayList<>(); - useCase.getPetriNet().getDataSet().forEach((fieldId, field) -> { + // TODO: release/8.0.0 depending fields + useCase.getProcess().getDataSet().forEach((fieldId, field) -> { Field<?> useCaseField = field.clone(); useCase.getDataSet().put(fieldId, useCaseField); - if (field.isImmediate()) { + if (field.getImmediate() != null && field.getImmediate()) { useCase.getImmediateDataFields().add(field.getStringId()); useCase.getImmediateData().add(useCaseField); } - if (useCaseField.isDynamicDefaultValue()) { - dynamicValueFields.add(useCaseField); - } else { - useCaseField.applyDefaultValue(); - } if (useCaseField instanceof ChoiceField) { ChoiceField<?> choiceField = (ChoiceField<?>) useCaseField; if (choiceField.isDynamic()) { - dynamicChoiceFields.add(choiceField); + initializeChoices(useCase, choiceField, params); } } if (useCaseField instanceof MapOptionsField) { - MapOptionsField<I18nString,?> optionsField = (MapOptionsField<I18nString, ?>) useCaseField; + MapOptionsField<I18nString, ?> optionsField = (MapOptionsField<I18nString, ?>) useCaseField; if (optionsField.isDynamic()) { - dynamicOptionFields.add(optionsField); + initializeOptions(useCase, optionsField, params); + } + } + if (useCaseField.getDefaultValue() != null) { + if (useCaseField.getDefaultValue().isDynamic()) { + initializeValue(useCase, useCaseField, params); + } else { + useCaseField.applyDefaultValue(); + if (useCaseField instanceof TaskField && useCaseField.getRawValue() != null) { + TaskField taskRef = (TaskField) useCaseField; + String value = taskRef.getRawValue().get(0); + taskRef.setRawValue(Arrays.stream(value.split(",")) + .map(useCase::getTaskStringId) + .collect(Collectors.toList())); + } } } }); - - dynamicChoiceFields.forEach(f -> this.initializeChoices(useCase, f, params)); - dynamicOptionFields.forEach(f -> this.initializeOptions(useCase, f, params)); - dynamicValueFields.forEach(f -> this.initializeValue(useCase, f, params)); } - public <t> void initializeValue(Case useCase, Field<t> field, Map<String, String> params) { - field.setRawValue(initValueExpressionEvaluator.evaluate(useCase, field, params)); + public <T> void initializeValue(Case useCase, Field<T> field, Map<String, String> params) { + field.setRawValue(initValueExpressionEvaluator.evaluateValue(useCase, field, params)); } public void initializeChoices(Case useCase, ChoiceField<?> field, Map<String, String> params) { diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IUserFilterSearchService.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IActorFilterSearchService.java similarity index 82% rename from src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IUserFilterSearchService.java rename to src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IActorFilterSearchService.java index 5689e4c41b0..f76520d447b 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IUserFilterSearchService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IActorFilterSearchService.java @@ -4,6 +4,6 @@ import java.util.List; -public interface IUserFilterSearchService { +public interface IActorFilterSearchService { List<Case> autocompleteFindFilters(String userInput); } diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IConfigurableMenuService.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IConfigurableMenuService.java index 8d8a993c967..ef6cc5d6143 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IConfigurableMenuService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IConfigurableMenuService.java @@ -1,19 +1,13 @@ package com.netgrif.application.engine.workflow.service.interfaces; -import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.petrinet.domain.I18nString; import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField; import com.netgrif.application.engine.petrinet.domain.dataset.MultichoiceMapField; -import java.util.Locale; import java.util.Map; public interface IConfigurableMenuService { - Map<String, I18nString> getNetsByAuthorAsMapOptions(IUser author, Locale locale); - - Map<String, I18nString> getAvailableRolesFromNet(EnumerationMapField processField, MultichoiceMapField permittedRoles, MultichoiceMapField bannedRoles); - Map<String, I18nString> addSelectedRoles(MultichoiceMapField selected, EnumerationMapField netField, MultichoiceMapField roles); Map<String, I18nString> removeSelectedRoles(MultichoiceMapField addedRoles); diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ICrudSystemCaseService.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ICrudSystemCaseService.java new file mode 100644 index 00000000000..404d9083a08 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ICrudSystemCaseService.java @@ -0,0 +1,19 @@ +package com.netgrif.application.engine.workflow.service.interfaces; + +import com.netgrif.application.engine.workflow.domain.CaseParams; +import com.netgrif.application.engine.workflow.domain.SystemCase; + +import java.util.List; +import java.util.Optional; +import java.util.Set; + +public interface ICrudSystemCaseService<T extends SystemCase> { + boolean registerForbiddenKeywords(Set<String> keywords); + boolean removeForbiddenKeywords(Set<String> keywords); + void clearForbiddenKeywords(); + T create(CaseParams params) throws IllegalArgumentException, IllegalStateException; + T update(T systemObject, CaseParams params) throws IllegalArgumentException, IllegalStateException; + Optional<T> findById(String id); + boolean existsById(String id); + List<T> findAll(); +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IDataService.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IDataService.java index 30ff05446da..aa9173d5686 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IDataService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IDataService.java @@ -1,22 +1,17 @@ package com.netgrif.application.engine.workflow.service.interfaces; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.netgrif.application.engine.petrinet.domain.Component; +import com.netgrif.application.engine.petrinet.domain.dataset.UserFieldValue; import com.netgrif.application.engine.petrinet.domain.dataset.Field; import com.netgrif.application.engine.petrinet.domain.dataset.FileField; import com.netgrif.application.engine.petrinet.domain.dataset.FileListField; -import com.netgrif.application.engine.petrinet.domain.dataset.UserFieldValue; import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.QTask; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.GetDataEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.GetDataGroupsEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.GetDataEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.layoutoutcomes.GetLayoutsEventOutcome; +import com.netgrif.application.engine.workflow.domain.params.GetDataParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; import com.netgrif.application.engine.workflow.service.FileFieldInputStream; -import com.netgrif.application.engine.workflow.web.responsebodies.DataSet; -import com.querydsl.core.types.Predicate; import org.springframework.data.domain.Page; import org.springframework.web.multipart.MultipartFile; @@ -29,33 +24,13 @@ public interface IDataService { - GetDataEventOutcome getData(String taskId, IUser user); - - GetDataEventOutcome getData(String taskId, IUser user, Map<String, String> params); - - GetDataEventOutcome getData(Task task, Case useCase, IUser user); - - GetDataEventOutcome getData(Task task, Case useCase, IUser user, Map<String, String> params); - - SetDataEventOutcome setData(String taskId, DataSet values, IUser user); - - SetDataEventOutcome setData(String taskId, DataSet values, IUser user, Map<String, String> params); + GetDataEventOutcome getData(GetDataParams getDataParams); - SetDataEventOutcome setData(String taskId, DataSet values, LoggedUser loggedUser); + SetDataEventOutcome setData(SetDataParams setDataParams); - SetDataEventOutcome setData(String taskId, DataSet values, LoggedUser loggedUser, Map<String, String> params); - - SetDataEventOutcome setData(Case useCase, DataSet dataSet, IUser user); - - SetDataEventOutcome setData(Case useCase, DataSet dataSet, IUser user, Map<String, String> params); - - SetDataEventOutcome setData(Task task, DataSet values, IUser user); - - SetDataEventOutcome setData(Task task, DataSet values, IUser user, Map<String, String> params); - - SetDataEventOutcome setDataField(Task task, String fieldId, Field<?> newDataField, IUser user); + SetDataEventOutcome setDataField(Task task, String fieldId, Field<?> newDataField, String actorId); - SetDataEventOutcome setDataField(Task task, String fieldId, Field<?> newDataField, IUser user, Map<String, String> params); + SetDataEventOutcome setDataField(Task task, String fieldId, Field<?> newDataField, String actorId, Map<String, String> params); FileFieldInputStream getFile(Case useCase, Task task, FileField field, boolean forPreview); @@ -97,9 +72,7 @@ public interface IDataService { SetDataEventOutcome deleteFileByName(String taskId, String fieldId, String name, Map<String, String> params); // TODO: release/8.0.0 deprecated by forms - GetDataGroupsEventOutcome getDataGroups(String taskId, Locale locale, IUser user); - - GetDataGroupsEventOutcome getDataGroups(String taskId, Locale locale, LoggedUser loggedUser); + GetLayoutsEventOutcome getLayouts(String taskId, Locale locale, String actorId); // TODO: release/8.0.0 revision Page<Task> setImmediateFields(Page<Task> tasks); @@ -108,7 +81,5 @@ public interface IDataService { UserFieldValue makeUserFieldValue(String id); - Case applyFieldConnectedChanges(Case useCase, Field<?> field); - void validateCaseRefValue(List<String> value, List<String> allowedNets) throws IllegalArgumentException; } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IDataValidationExpressionEvaluator.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IDataValidationExpressionEvaluator.java deleted file mode 100644 index 720606d5ac0..00000000000 --- a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IDataValidationExpressionEvaluator.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.netgrif.application.engine.workflow.service.interfaces; - -import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; -import com.netgrif.application.engine.workflow.domain.Case; - -public interface IDataValidationExpressionEvaluator { - - String compile(Case useCase, Expression expression); - -} \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IEventService.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IEventService.java index dbdc45649f4..054371eeb55 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IEventService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IEventService.java @@ -7,8 +7,8 @@ import com.netgrif.application.engine.petrinet.domain.events.EventPhase; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome; import java.util.List; import java.util.Map; diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFieldActionsCacheService.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFieldActionsCacheService.java index e55c037c3ed..69a2a97139d 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFieldActionsCacheService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFieldActionsCacheService.java @@ -1,7 +1,7 @@ package com.netgrif.application.engine.workflow.service.interfaces; import com.netgrif.application.engine.petrinet.domain.Function; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action; import com.netgrif.application.engine.workflow.domain.CachedFunction; import groovy.lang.Closure; @@ -11,9 +11,9 @@ public interface IFieldActionsCacheService { - void cachePetriNetFunctions(PetriNet petriNet); + void cachePetriNetFunctions(Process petriNet); - void reloadCachedFunctions(PetriNet petriNet); + void reloadCachedFunctions(Process petriNet); Closure getCompiledAction(Action action, boolean shouldRewriteCachedActions); diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFilterImportExportService.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFilterImportExportService.java index 6a4cd89ef46..259debf471f 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFilterImportExportService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFilterImportExportService.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.workflow.service.interfaces; -import com.netgrif.application.engine.auth.domain.IUser; +import com.netgrif.application.engine.authorization.domain.Actor; import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.workflow.domain.filter.FilterImportExportList; import com.netgrif.application.engine.petrinet.domain.dataset.FileFieldValue; @@ -26,9 +26,9 @@ public interface IFilterImportExportService { Map<String, String> importFilters(FilterImportExportList filters) throws IOException, TransitionNotExecutableException; - void createFilterImport(IUser author); + void createFilterImport(Actor author); - void createFilterExport(IUser author); + void createFilterExport(Actor author); void changeFilterField(Collection<String> filterFields); } diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IInitValueExpressionEvaluator.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IInitValueExpressionEvaluator.java index 4a1c9f7f599..7304843fc7d 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IInitValueExpressionEvaluator.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IInitValueExpressionEvaluator.java @@ -7,18 +7,19 @@ import com.netgrif.application.engine.petrinet.domain.dataset.logic.Expression; import com.netgrif.application.engine.workflow.domain.Case; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; -import java.util.Set; public interface IInitValueExpressionEvaluator { - <T> T evaluate(Case useCase, Field<T> defaultField, Map<String, String> params); + <T> T evaluateValue(Case useCase, Field<T> defaultField, Map<String, String> params); - Map<String, I18nString> evaluateOptions(Case useCase, MapOptionsField<I18nString, ?> field, Map<String, String> params); + LinkedHashMap<String, I18nString> evaluateOptions(Case useCase, MapOptionsField<I18nString, ?> field, Map<String, String> params); - Set<I18nString> evaluateChoices(Case useCase, ChoiceField field, Map<String, String> params); + <T> LinkedHashSet<I18nString> evaluateChoices(Case useCase, ChoiceField<T> field, Map<String, String> params); - I18nString evaluateCaseName(Case useCase, Expression expression, Map<String, String> params); + <T> T evaluate(Case useCase, Expression<T> expression, Map<String, String> params); - Object evaluate(Case useCase, Expression expression, Map<String, String> params); + String evaluateTitle(Expression<String> expression, Map<String, String> params); } diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ITaskAuthorizationService.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ITaskAuthorizationService.java deleted file mode 100644 index e65e9a3d013..00000000000 --- a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ITaskAuthorizationService.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.netgrif.application.engine.workflow.service.interfaces; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.petrinet.domain.roles.RolePermission; -import com.netgrif.application.engine.petrinet.domain.throwable.IllegalTaskStateException; -import com.netgrif.application.engine.workflow.domain.Task; - -public interface ITaskAuthorizationService { - Boolean userHasAtLeastOneRolePermission(LoggedUser loggedUser, String taskId, RolePermission... permissions); - - Boolean userHasAtLeastOneRolePermission(IUser user, Task task, RolePermission... permissions); - - Boolean userHasUserListPermission(LoggedUser loggedUser, String taskId, RolePermission... permissions); - - Boolean userHasUserListPermission(IUser user, Task task, RolePermission... permissions); - - boolean isAssignee(LoggedUser loggedUser, String taskId); - - boolean isAssignee(IUser user, String taskId); - - boolean isAssignee(IUser user, Task task); - - boolean canCallAssign(LoggedUser loggedUser, String taskId); - - boolean canCallDelegate(LoggedUser loggedUser, String taskId); - - boolean canCallFinish(LoggedUser loggedUser, String taskId) throws IllegalTaskStateException; - - boolean canCallCancel(LoggedUser loggedUser, String taskId) throws IllegalTaskStateException; - - boolean canCallSaveData(LoggedUser loggedUser, String taskId); - - boolean canCallSaveFile(LoggedUser loggedUser, String taskId); - -} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ITaskService.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ITaskService.java index 31fd7c66c95..71773aeb9fc 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ITaskService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ITaskService.java @@ -1,45 +1,49 @@ package com.netgrif.application.engine.workflow.service.interfaces; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.TaskNotFoundException; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.AssignTaskEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.CancelTaskEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.DelegateTaskEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.FinishTaskEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.CreateTasksOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.EventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.AssignTaskEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.CancelTaskEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.DelegateTaskEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.FinishTaskEventOutcome; +import com.netgrif.application.engine.workflow.domain.params.TaskParams; import com.netgrif.application.engine.workflow.web.requestbodies.TaskSearchRequest; import com.netgrif.application.engine.workflow.web.responsebodies.TaskReference; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Set; // TODO: release/8.0.0 remove LoggedUser, create TaskEventContext class to merge all params public interface ITaskService { - void reloadTasks(Case useCase); + boolean reloadTasks(Case useCase); + + boolean isAssigned(Task task); + + CreateTasksOutcome createAndSetTasksInCase(Case useCase); Task findOne(String taskId); - Page<Task> getAll(LoggedUser loggedUser, Pageable pageable, Locale locale); + Page<Task> getAll(String actorId, Pageable pageable, Locale locale); - Page<Task> search(List<TaskSearchRequest> requests, Pageable pageable, LoggedUser user, Locale locale, Boolean isIntersection); + Page<Task> search(List<TaskSearchRequest> requests, Pageable pageable, String actorId, Locale locale, Boolean isIntersection); - long count(List<TaskSearchRequest> requests, LoggedUser user, Locale locale, Boolean isIntersection); + long count(List<TaskSearchRequest> requests, String actorId, Locale locale, Boolean isIntersection); Page<Task> findByCases(Pageable pageable, List<String> cases); List<Task> findAllById(List<String> ids); - Page<Task> findByUser(Pageable pageable, IUser user); + Page<Task> findByAssignee(Pageable pageable, String actorId); + + boolean existsByTaskAndAssignee(String taskId, String assigneeId); Task findById(String id); @@ -51,58 +55,24 @@ public interface ITaskService { Task searchOne(com.querydsl.core.types.Predicate predicate); - List<FinishTaskEventOutcome> finishTasks(List<Task> tasks, IUser user) throws TransitionNotExecutableException; - - List<FinishTaskEventOutcome> finishTasks(List<Task> tasks, IUser user, Map<String, String> params) throws TransitionNotExecutableException; - - FinishTaskEventOutcome finishTask(Task task, IUser user) throws TransitionNotExecutableException; - - FinishTaskEventOutcome finishTask(Task task, IUser user, Map<String, String> params) throws TransitionNotExecutableException; - - FinishTaskEventOutcome finishTask(LoggedUser loggedUser, String taskId) throws IllegalArgumentException, TransitionNotExecutableException; - - FinishTaskEventOutcome finishTask(LoggedUser loggedUser, String taskId, Map<String, String> params) throws IllegalArgumentException, TransitionNotExecutableException; - - FinishTaskEventOutcome finishTask(String taskId) throws IllegalArgumentException, TransitionNotExecutableException; - - FinishTaskEventOutcome finishTask(String taskId, Map<String, String> params) throws IllegalArgumentException, TransitionNotExecutableException; + List<EventOutcome> executeTask(Task task, Case useCase); - List<AssignTaskEventOutcome> assignTasks(List<Task> tasks, IUser user) throws TransitionNotExecutableException; + List<FinishTaskEventOutcome> finishTasks(List<Task> tasks, String actorId, Map<String, String> params) throws TransitionNotExecutableException; - List<AssignTaskEventOutcome> assignTasks(List<Task> tasks, IUser user, Map<String, String> params) throws TransitionNotExecutableException; + FinishTaskEventOutcome finishTask(TaskParams taskParams) throws TransitionNotExecutableException; - AssignTaskEventOutcome assignTask(Task task, IUser user) throws TransitionNotExecutableException; + List<AssignTaskEventOutcome> assignTasks(List<Task> tasks, String actorId, Map<String, String> params) throws TransitionNotExecutableException; - AssignTaskEventOutcome assignTask(Task task, IUser user, Map<String, String> params) throws TransitionNotExecutableException; + AssignTaskEventOutcome assignTask(TaskParams taskParams) throws TransitionNotExecutableException; - AssignTaskEventOutcome assignTask(LoggedUser loggedUser, String taskId) throws TransitionNotExecutableException, TaskNotFoundException; + List<CancelTaskEventOutcome> cancelTasks(List<Task> tasks, String actorId, Map<String, String> params); - AssignTaskEventOutcome assignTask(LoggedUser loggedUser, String taskId, Map<String, String> params) throws TransitionNotExecutableException, TaskNotFoundException; - - AssignTaskEventOutcome assignTask(String taskId) throws TransitionNotExecutableException; - - AssignTaskEventOutcome assignTask(String taskId, Map<String, String> params) throws TransitionNotExecutableException; - - List<CancelTaskEventOutcome> cancelTasks(List<Task> tasks, IUser user); - - List<CancelTaskEventOutcome> cancelTasks(List<Task> tasks, IUser user, Map<String, String> params); - - CancelTaskEventOutcome cancelTask(Task task, IUser user); - - CancelTaskEventOutcome cancelTask(Task task, IUser user, Map<String, String> params); - - CancelTaskEventOutcome cancelTask(LoggedUser loggedUser, String taskId); - - CancelTaskEventOutcome cancelTask(LoggedUser loggedUser, String taskId, Map<String, String> params); + CancelTaskEventOutcome cancelTask(TaskParams taskParams); // TODO: release/8.0.0 delegate is deprecated - DelegateTaskEventOutcome delegateTask(LoggedUser loggedUser, String delegatedId, String taskId) throws TransitionNotExecutableException; - - DelegateTaskEventOutcome delegateTask(LoggedUser loggedUser, String delegatedId, String taskId, Map<String, String> params) throws TransitionNotExecutableException; - - void resolveUserRef(Case useCase); + DelegateTaskEventOutcome delegateTask(String actorId, String delegatedId, String taskId) throws TransitionNotExecutableException; - Task resolveUserRef(Task task, Case useCase); + DelegateTaskEventOutcome delegateTask(String actorId, String delegatedId, String taskId, Map<String, String> params) throws TransitionNotExecutableException; void delete(List<Task> tasks, Case useCase); diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowAuthorizationService.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowAuthorizationService.java deleted file mode 100644 index ba9797e043a..00000000000 --- a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowAuthorizationService.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.netgrif.application.engine.workflow.service.interfaces; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission; -import com.netgrif.application.engine.workflow.domain.Case; - -public interface IWorkflowAuthorizationService { - - boolean canCallDelete(LoggedUser user, String caseId); - - boolean canCallCreate(LoggedUser user, String netId); - - Boolean userHasAtLeastOneRolePermission(IUser user, PetriNet net, ProcessRolePermission... permissions); - - Boolean userHasUserListPermission(IUser user, Case useCase, ProcessRolePermission... permissions); -} diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowService.java b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowService.java index 875fe09f89f..5776f178561 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowService.java @@ -1,19 +1,17 @@ package com.netgrif.application.engine.workflow.service.interfaces; -import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.petrinet.domain.I18nString; -import com.netgrif.application.engine.petrinet.domain.PetriNet; -import com.netgrif.application.engine.petrinet.domain.dataset.Field; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.DeleteCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.DeleteCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.DeleteCaseParams; import com.querydsl.core.types.Predicate; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import java.util.List; -import java.util.Locale; import java.util.Map; public interface IWorkflowService { @@ -28,37 +26,15 @@ public interface IWorkflowService { Page<Case> getAll(Pageable pageable); - Case resolveUserRef(Case useCase); - - CreateCaseEventOutcome createCase(String netId, String title, String color, LoggedUser user, Locale locale, Map<String, String> params); - - CreateCaseEventOutcome createCase(String netId, String title, String color, LoggedUser user, Locale locale); - - CreateCaseEventOutcome createCase(String netId, String title, String color, LoggedUser user, Map<String, String> params); - - CreateCaseEventOutcome createCase(String netId, String title, String color, LoggedUser user); - - CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user, Map<String, String> params); - - CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user); - - CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user, Locale locale, Map<String, String> params); - - CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user, Locale locale); + CreateCaseEventOutcome createCase(CreateCaseParams createCaseParams); Page<Case> findAllByAuthor(String authorId, String petriNet, Pageable pageable); - DeleteCaseEventOutcome deleteCase(String caseId, Map<String, String> params); - - DeleteCaseEventOutcome deleteCase(String caseId); - DeleteCaseEventOutcome deleteSubtreeRootedAt(String caseId); - DeleteCaseEventOutcome deleteCase(Case useCase, Map<String, String> params); - - DeleteCaseEventOutcome deleteCase(Case useCase); + DeleteCaseEventOutcome deleteCase(DeleteCaseParams deleteCaseParams); - void deleteInstancesOfPetriNet(PetriNet net); + void deleteInstancesOfPetriNet(Process net); void updateMarking(Case useCase); @@ -72,9 +48,9 @@ public interface IWorkflowService { Map<String, I18nString> listToMap(List<Case> cases); - void removeTasksFromCase(List<Task> tasks, String caseId); - - void removeTasksFromCase(List<Task> tasks, Case useCase); +// TODO: release/8.0.0 +// void removeTasksFromCase(List<Task> tasks, String caseId); +// void removeTasksFromCase(List<Task> tasks, Case useCase); Case decrypt(Case useCase); diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/throwable/CaseAlreadyExistsException.java b/src/main/java/com/netgrif/application/engine/workflow/service/throwable/CaseAlreadyExistsException.java new file mode 100644 index 00000000000..41c6f94c56c --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/workflow/service/throwable/CaseAlreadyExistsException.java @@ -0,0 +1,8 @@ +package com.netgrif.application.engine.workflow.service.throwable; + +public class CaseAlreadyExistsException extends RuntimeException { + + public CaseAlreadyExistsException(String message) { + super(message); + } +} diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/AbstractTaskController.java b/src/main/java/com/netgrif/application/engine/workflow/web/AbstractTaskController.java index bdbb309c038..d713334fb11 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/AbstractTaskController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/AbstractTaskController.java @@ -1,16 +1,18 @@ package com.netgrif.application.engine.workflow.web; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; import com.netgrif.application.engine.elastic.web.requestbodies.singleaslist.SingleElasticTaskSearchRequestAsList; import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.workflow.domain.IllegalArgumentWithChangedFieldsException; import com.netgrif.application.engine.workflow.domain.MergeFilterOperation; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.GetDataGroupsEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessage; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessageResource; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.layoutoutcomes.GetLayoutsEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response.EventOutcomeWithMessage; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response.EventOutcomeWithMessageResource; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.domain.params.TaskParams; import com.netgrif.application.engine.workflow.service.FileFieldInputStream; import com.netgrif.application.engine.workflow.service.interfaces.IDataService; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; @@ -55,8 +57,8 @@ public AbstractTaskController(ITaskService taskService, IDataService dataService } public PagedModel<TaskResource> getAll(Authentication auth, Pageable pageable, PagedResourcesAssembler<Task> assembler, Locale locale) { - LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); - Page<Task> page = taskService.getAll(loggedUser, pageable, locale); + LoggedIdentity identity = (LoggedIdentity) auth.getPrincipal(); + Page<Task> page = taskService.getAll(identity.getActiveActorId(), pageable, locale); Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(TaskController.class) .getAll(auth, pageable, assembler, locale)).withRel("all"); @@ -87,27 +89,38 @@ public TaskResource getOne(String taskId, Locale locale) { return new TaskResource(task); } - public EntityModel<EventOutcomeWithMessage> assign(LoggedUser loggedUser, String taskId) { + public EntityModel<EventOutcomeWithMessage> assign(LoggedIdentity identity, String taskId) { try { - return EventOutcomeWithMessageResource.successMessage("LocalisedTask " + taskId + " assigned to " + loggedUser.getFullName(), taskService.assignTask(loggedUser, taskId)); + TaskParams taskParams = TaskParams.with() + .taskId(taskId) + .assigneeId(identity.getActiveActorId()) + .build(); + return EventOutcomeWithMessageResource.successMessage("LocalisedTask " + taskId + " assigned to " + identity.getUsername(), + taskService.assignTask(taskParams)); } catch (TransitionNotExecutableException e) { log.error("Assigning task [{}] failed: ", taskId, e); return EventOutcomeWithMessageResource.errorMessage("LocalisedTask " + taskId + " cannot be assigned"); } } - public EntityModel<EventOutcomeWithMessage> delegate(LoggedUser loggedUser, String taskId, String delegatedId) { + public EntityModel<EventOutcomeWithMessage> delegate(LoggedIdentity identity, String taskId, String delegatedId) { try { - return EventOutcomeWithMessageResource.successMessage("LocalisedTask " + taskId + " assigned to [" + delegatedId + "]", taskService.delegateTask(loggedUser, delegatedId, taskId)); + return EventOutcomeWithMessageResource.successMessage("LocalisedTask " + taskId + " assigned to [" + delegatedId + "]", + taskService.delegateTask(identity.getActiveActorId(), delegatedId, taskId)); } catch (Exception e) { log.error("Delegating task [{}] failed: ", taskId, e); return EventOutcomeWithMessageResource.errorMessage("LocalisedTask " + taskId + " cannot be assigned"); } } - public EntityModel<EventOutcomeWithMessage> finish(LoggedUser loggedUser, String taskId) { + public EntityModel<EventOutcomeWithMessage> finish(LoggedIdentity identity, String taskId) { try { - return EventOutcomeWithMessageResource.successMessage("LocalisedTask " + taskId + " finished", taskService.finishTask(loggedUser, taskId)); + TaskParams taskParams = TaskParams.with() + .taskId(taskId) + .assigneeId(identity.getActiveActorId()) + .build(); + return EventOutcomeWithMessageResource.successMessage("LocalisedTask " + taskId + " finished", + taskService.finishTask(taskParams)); } catch (Exception e) { log.error("Finishing task [{}] failed: ", taskId, e); if (e instanceof IllegalArgumentWithChangedFieldsException) { @@ -118,9 +131,14 @@ public EntityModel<EventOutcomeWithMessage> finish(LoggedUser loggedUser, String } } - public EntityModel<EventOutcomeWithMessage> cancel(LoggedUser loggedUser, String taskId) { + public EntityModel<EventOutcomeWithMessage> cancel(LoggedIdentity identity, String taskId) { try { - return EventOutcomeWithMessageResource.successMessage("LocalisedTask " + taskId + " canceled", taskService.cancelTask(loggedUser, taskId)); + TaskParams taskParams = TaskParams.with() + .taskId(taskId) + .assigneeId(identity.getActiveActorId()) + .build(); + return EventOutcomeWithMessageResource.successMessage("LocalisedTask " + taskId + " canceled", + taskService.cancelTask(taskParams)); } catch (Exception e) { log.error("Canceling task [{}] failed: ", taskId, e); if (e instanceof IllegalArgumentWithChangedFieldsException) { @@ -132,7 +150,7 @@ public EntityModel<EventOutcomeWithMessage> cancel(LoggedUser loggedUser, String } public PagedModel<TaskResource> getMy(Authentication auth, Pageable pageable, PagedResourcesAssembler<Task> assembler, Locale locale) { - Page<Task> page = taskService.findByUser(pageable, ((LoggedUser) auth.getPrincipal()).transformToUser()); + Page<Task> page = taskService.findByAssignee(pageable, ((LoggedIdentity) auth.getPrincipal()).getActiveActorId()); Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(TaskController.class) .getMy(auth, pageable, assembler, locale)).withRel("my"); @@ -142,7 +160,7 @@ public PagedModel<TaskResource> getMy(Authentication auth, Pageable pageable, Pa } public PagedModel<TaskResource> getMyFinished(Pageable pageable, Authentication auth, PagedResourcesAssembler<Task> assembler, Locale locale) { - Page<Task> page = taskService.findByUser(pageable, ((LoggedUser) auth.getPrincipal()).transformToUser()); + Page<Task> page = taskService.findByAssignee(pageable, ((LoggedIdentity) auth.getPrincipal()).getActiveActorId()); Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(TaskController.class) .getMyFinished(pageable, auth, assembler, locale)).withRel("finished"); @@ -152,7 +170,8 @@ public PagedModel<TaskResource> getMyFinished(Pageable pageable, Authentication } public PagedModel<TaskResource> search(Authentication auth, Pageable pageable, SingleTaskSearchRequestAsList searchBody, MergeFilterOperation operation, PagedResourcesAssembler<Task> assembler, Locale locale) { - Page<Task> tasks = taskService.search(searchBody.getList(), pageable, (LoggedUser) auth.getPrincipal(), locale, operation == MergeFilterOperation.AND); + Page<Task> tasks = taskService.search(searchBody.getList(), pageable, ((LoggedIdentity) auth.getPrincipal()).getActiveActorId(), + locale, operation == MergeFilterOperation.AND); Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(TaskController.class) .search(auth, pageable, searchBody, operation, assembler, locale)).withRel("search"); PagedModel<TaskResource> resources = assembler.toModel(tasks, new TaskResourceAssembler(), selfLink); @@ -160,17 +179,19 @@ public PagedModel<TaskResource> search(Authentication auth, Pageable pageable, S return resources; } - public PagedModel<TaskResource> searchPublic(LoggedUser loggedUser, Pageable pageable, SingleTaskSearchRequestAsList searchBody, MergeFilterOperation operation, PagedResourcesAssembler<com.netgrif.application.engine.workflow.domain.Task> assembler, Locale locale) { - Page<com.netgrif.application.engine.workflow.domain.Task> tasks = taskService.search(searchBody.getList(), pageable, loggedUser, locale, operation == MergeFilterOperation.AND); + public PagedModel<TaskResource> searchPublic(LoggedIdentity identity, Pageable pageable, SingleTaskSearchRequestAsList searchBody, MergeFilterOperation operation, PagedResourcesAssembler<com.netgrif.application.engine.workflow.domain.Task> assembler, Locale locale) { + Page<com.netgrif.application.engine.workflow.domain.Task> tasks = taskService.search(searchBody.getList(), pageable, + identity.getActiveActorId(), locale, operation == MergeFilterOperation.AND); Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(PublicTaskController.class) - .searchPublic(loggedUser, pageable, searchBody, operation, assembler, locale)).withRel("search"); + .searchPublic(identity, pageable, searchBody, operation, assembler, locale)).withRel("search"); PagedModel<TaskResource> resources = assembler.toModel(tasks, new TaskResourceAssembler(), selfLink); ResourceLinkAssembler.addLinks(resources, Task.class, selfLink.getRel().toString()); return resources; } public PagedModel<TaskResource> searchElastic(Authentication auth, Pageable pageable, SingleElasticTaskSearchRequestAsList searchBody, MergeFilterOperation operation, PagedResourcesAssembler<Task> assembler, Locale locale) { - Page<Task> tasks = searchService.search(searchBody.getList(), (LoggedUser) auth.getPrincipal(), pageable, locale, operation == MergeFilterOperation.AND); + LoggedIdentity identity = (LoggedIdentity) auth.getPrincipal(); + Page<Task> tasks = searchService.search(searchBody.getList(), identity.getActiveActorId(), pageable, locale, operation == MergeFilterOperation.AND); Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(TaskController.class) .searchElastic(auth, pageable, searchBody, operation, assembler, locale)).withRel("search_es"); PagedModel<TaskResource> resources = assembler.toModel(tasks, new TaskResourceAssembler(), selfLink); @@ -179,14 +200,15 @@ public PagedModel<TaskResource> searchElastic(Authentication auth, Pageable page } public CountResponse count(SingleElasticTaskSearchRequestAsList query, MergeFilterOperation operation, Authentication auth, Locale locale) { - long count = searchService.count(query.getList(), (LoggedUser) auth.getPrincipal(), locale, operation == MergeFilterOperation.AND); + LoggedIdentity identity = (LoggedIdentity) auth.getPrincipal(); + long count = searchService.count(query.getList(), identity.getActiveActorId(), locale, operation == MergeFilterOperation.AND); return CountResponse.taskCount(count); } - +//// TODO: release/8.0.0 fix public EntityModel<EventOutcomeWithMessage> getData(String taskId, Locale locale, Authentication auth) { try { - GetDataGroupsEventOutcome outcome = dataService.getDataGroups(taskId, locale, (LoggedUser) auth.getPrincipal()); + GetLayoutsEventOutcome outcome = dataService.getLayouts(taskId, locale, ((LoggedIdentity) auth.getPrincipal()).getActiveActorId()); return EventOutcomeWithMessageResource.successMessage("Get data groups successful", outcome); } catch (IllegalArgumentWithChangedFieldsException e) { log.error("Get data on task [{}] failed: ", taskId, e); @@ -200,7 +222,8 @@ public EntityModel<EventOutcomeWithMessage> getData(String taskId, Locale locale public EntityModel<EventOutcomeWithMessage> setData(String taskId, TaskDataSets dataBody, Authentication auth) { try { Map<String, SetDataEventOutcome> outcomes = new HashMap<>(); - dataBody.getBody().forEach((task, dataSet) -> outcomes.put(task, dataService.setData(task, dataSet, (LoggedUser) auth.getPrincipal()))); + dataBody.getBody().forEach((task, dataSet) -> outcomes.put(task, dataService.setData(new SetDataParams(task, + dataSet, ((LoggedIdentity) auth.getPrincipal()).getActiveActorId())))); SetDataEventOutcome mainOutcome = taskService.getMainOutcome(outcomes, taskId); return EventOutcomeWithMessageResource.successMessage("Data field values have been successfully set", mainOutcome); } catch (IllegalArgumentWithChangedFieldsException e) { diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java b/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java index 724f7c9302c..b056d5edb25 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java @@ -1,9 +1,9 @@ package com.netgrif.application.engine.workflow.web; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; import com.netgrif.application.engine.workflow.domain.MergeFilterOperation; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessage; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response.EventOutcomeWithMessage; import com.netgrif.application.engine.workflow.service.interfaces.IDataService; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.web.requestbodies.file.FileFieldRequest; @@ -46,12 +46,12 @@ public class PublicTaskController extends AbstractTaskController { final ITaskService taskService; - final IUserService userService; + final ISessionManagerService sessionManagerService; - public PublicTaskController(ITaskService taskService, IDataService dataService, IUserService userService) { + public PublicTaskController(ITaskService taskService, IDataService dataService, ISessionManagerService sessionManagerService) { super(taskService, dataService, null); this.taskService = taskService; - this.userService = userService; + this.sessionManagerService = sessionManagerService; } @Override @@ -61,7 +61,7 @@ public List<TaskReference> getTasksOfCase(@PathVariable("id") String caseId, Loc return this.taskService.findAllByCase(caseId, locale); } - @PreAuthorize("@taskAuthorizationService.canCallAssign(@userService.getAnonymousLogged(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallAssign(#taskId)") @GetMapping(value = "/assign/{id}", produces = MediaTypes.HAL_JSON_VALUE) @Operation(summary = "Assign task", description = "Caller must be able to perform the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -72,11 +72,11 @@ public List<TaskReference> getTasksOfCase(@PathVariable("id") String caseId, Loc description = "Caller doesn't fulfill the authorisation requirements" )}) public EntityModel<EventOutcomeWithMessage> assign(@PathVariable("id") String taskId) { - LoggedUser loggedUser = userService.getAnonymousLogged(); - return super.assign(loggedUser, taskId); + LoggedIdentity identity = sessionManagerService.getLoggedIdentity(); + return super.assign(identity, taskId); } - @PreAuthorize("@taskAuthorizationService.canCallFinish(@userService.getAnonymousLogged(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallFinish(#taskId)") @GetMapping(value = "/finish/{id}", produces = MediaTypes.HAL_JSON_VALUE) @Operation(summary = "Finish task", description = "Caller must be assigned to the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -87,11 +87,11 @@ public EntityModel<EventOutcomeWithMessage> assign(@PathVariable("id") String ta description = "Caller doesn't fulfill the authorisation requirements" )}) public EntityModel<EventOutcomeWithMessage> finish(@PathVariable("id") String taskId) { - LoggedUser loggedUser = userService.getAnonymousLogged(); - return super.finish(loggedUser, taskId); + LoggedIdentity identity = sessionManagerService.getLoggedIdentity(); + return super.finish(identity, taskId); } - @PreAuthorize("@taskAuthorizationService.canCallCancel(@userService.getAnonymousLogged(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallCancel(#taskId)") @GetMapping(value = "/cancel/{id}", produces = MediaTypes.HAL_JSON_VALUE) @Operation(summary = "Cancel task", description = "Caller must be assigned to the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -102,19 +102,20 @@ public EntityModel<EventOutcomeWithMessage> finish(@PathVariable("id") String ta description = "Caller doesn't fulfill the authorisation requirements" )}) public EntityModel<EventOutcomeWithMessage> cancel(@PathVariable("id") String taskId) { - LoggedUser loggedUser = userService.getAnonymousLogged(); - return super.cancel(loggedUser, taskId); + LoggedIdentity identity = sessionManagerService.getLoggedIdentity(); + return super.cancel(identity, taskId); } - @Override - @GetMapping(value = "/{id}/data", produces = MediaTypes.HAL_JSON_VALUE) - @Operation(summary = "Get all task data") - public EntityModel<EventOutcomeWithMessage> getData(@PathVariable("id") String taskId, Locale locale, Authentication auth) { - return super.getData(taskId, locale, auth); - } + // TODO: NAE-1969 fix +// @Override +// @GetMapping(value = "/{id}/data", produces = MediaTypes.HAL_JSON_VALUE) +// @Operation(summary = "Get all task data") +// public EntityModel<EventOutcomeWithMessage> getData(@PathVariable("id") String taskId, Locale locale, Authentication auth) { +// return super.getData(taskId, locale, auth); +// } @Override - @PreAuthorize("@taskAuthorizationService.canCallSaveData(@userService.getAnonymousLogged(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallSetData(#taskId)") @PostMapping(value = "/{id}/data", consumes = "application/json;charset=UTF-8", produces = "application/json;charset=UTF-8") @Operation(summary = "Set task data", description = "Caller must be assigned to the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -128,7 +129,7 @@ public EntityModel<EventOutcomeWithMessage> setData(@PathVariable("id") String t return super.setData(taskId, dataBody, auth); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#taskId)") @Operation(summary = "Upload file into the task", description = "Caller must be assigned to the task, or must be an ADMIN") @PostMapping(value = "/{id}/file", produces = MediaTypes.HAL_JSON_VALUE) @@ -147,7 +148,7 @@ public ResponseEntity<Resource> getFile(@PathVariable("id") String taskId, @Requ return super.getFile(taskId, fieldId); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#taskId)") @Operation(summary = "Remove file from the task", description = "Caller must be assigned to the task, or must be an ADMIN") @DeleteMapping(value = "/{id}/file", produces = MediaTypes.HAL_JSON_VALUE) @@ -167,7 +168,7 @@ public ResponseEntity<Resource> getFilePreview(@PathVariable("id") String taskId } @Override - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#taskId)") @Operation(summary = "Upload multiple files into the task", description = "Caller must be assigned to the task, or must be an ADMIN") @PostMapping(value = "/{id}/files", produces = MediaTypes.HAL_JSON_VALUE) @@ -186,7 +187,7 @@ public ResponseEntity<Resource> getNamedFile(@PathVariable("id") String taskId, return super.getNamedFile(taskId, fieldId, fileName); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#taskId)") @Operation(summary = "Remove file from tasks file list field value", description = "Caller must be assigned to the task, or must be an ADMIN") @DeleteMapping(value = "/{id}/file/named", produces = MediaTypes.HAL_JSON_VALUE) @@ -201,6 +202,6 @@ public EntityModel<EventOutcomeWithMessage> deleteNamedFile(@PathVariable("id") @Operation(summary = "Generic task search on Mongo database") @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public PagedModel<TaskResource> search(Pageable pageable, @RequestBody SingleTaskSearchRequestAsList searchBody, @RequestParam(defaultValue = "OR") MergeFilterOperation operation, PagedResourcesAssembler<com.netgrif.application.engine.workflow.domain.Task> assembler, Locale locale) { - return super.searchPublic(userService.getAnonymousLogged(), pageable, searchBody, operation, assembler, locale); + return super.searchPublic(sessionManagerService.getLoggedIdentity(), pageable, searchBody, operation, assembler, locale); } } diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java index 801ca6f5cd7..96a888f517d 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java @@ -1,14 +1,16 @@ package com.netgrif.application.engine.workflow.web; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessage; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessageResource; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response.EventOutcomeWithMessage; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response.EventOutcomeWithMessageResource; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import com.netgrif.application.engine.workflow.web.requestbodies.CreateCaseBody; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.hateoas.EntityModel; @@ -23,6 +25,7 @@ @Slf4j @RestController +@RequiredArgsConstructor @ConditionalOnProperty( value = "nae.public.workflow.web.enabled", havingValue = "true", @@ -33,24 +36,24 @@ public class PublicWorkflowController { private final IWorkflowService workflowService; + private final ISessionManagerService sessionManagerService; - private final IUserService userService; - - public PublicWorkflowController(IWorkflowService workflowService, IUserService userService) { - this.userService = userService; - this.workflowService = workflowService; - } - - @PreAuthorize("@workflowAuthorizationService.canCallCreate(@userService.getAnonymousLogged(), #body.netId)") + @PreAuthorize("@caseAuthorizationService.canCallCreate(#body.netId)") @PostMapping(value = "/case", consumes = "application/json;charset=UTF-8", produces = MediaTypes.HAL_JSON_VALUE) @Operation(summary = "Create new case") public EntityModel<EventOutcomeWithMessage> createCase(@RequestBody CreateCaseBody body, Locale locale) { - LoggedUser loggedUser = userService.getAnonymousLogged(); + LoggedIdentity identity = sessionManagerService.getLoggedIdentity(); try { - CreateCaseEventOutcome outcome = this.workflowService.createCase(body.netId, body.title, body.color, loggedUser, locale); + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processId(body.netId) + .title(body.title) + .authorId(identity.getActiveActorId()) + .locale(locale) + .build(); + CreateCaseEventOutcome outcome = this.workflowService.createCase(createCaseParams); return EventOutcomeWithMessageResource.successMessage("Case created successfully", outcome); } catch (Exception e) { - log.error("Creating case failed:" + e.getMessage(), e); + log.error("Creating case failed: {}", e.getMessage(), e); return EventOutcomeWithMessageResource.errorMessage("Creating case failed: " + e.getMessage()); } } diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java b/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java index 2713d655813..75f7353b24f 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java @@ -1,11 +1,11 @@ package com.netgrif.application.engine.workflow.web; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; import com.netgrif.application.engine.elastic.web.requestbodies.singleaslist.SingleElasticTaskSearchRequestAsList; import com.netgrif.application.engine.workflow.domain.MergeFilterOperation; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessage; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response.EventOutcomeWithMessage; import com.netgrif.application.engine.workflow.service.interfaces.IDataService; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.web.requestbodies.file.FileFieldRequest; @@ -81,7 +81,7 @@ public TaskResource getOne(@PathVariable("id") String taskId, Locale locale) { return super.getOne(taskId, locale); } - @PreAuthorize("@taskAuthorizationService.canCallAssign(#auth.getPrincipal(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallAssign(#taskId)") @Operation(summary = "Assign task", description = "Caller must be able to perform the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -91,11 +91,10 @@ public TaskResource getOne(@PathVariable("id") String taskId, Locale locale) { @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), }) public EntityModel<EventOutcomeWithMessage> assign(Authentication auth, @PathVariable("id") String taskId) { - LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); - return super.assign(loggedUser, taskId); + LoggedIdentity identity = (LoggedIdentity) auth.getPrincipal(); + return super.assign(identity, taskId); } - @PreAuthorize("@taskAuthorizationService.canCallDelegate(#auth.getPrincipal(), #taskId)") @Operation(summary = "Delegate task", description = "Caller must be able to delegate the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -105,11 +104,12 @@ public EntityModel<EventOutcomeWithMessage> assign(Authentication auth, @PathVar @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), }) public EntityModel<EventOutcomeWithMessage> delegate(Authentication auth, @PathVariable("id") String taskId, @RequestBody String delegatedId) { - LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); - return super.delegate(loggedUser, taskId, delegatedId); + // TODO: release/8.0.0 remove delegate + LoggedIdentity identity = (LoggedIdentity) auth.getPrincipal(); + return super.delegate(identity, taskId, delegatedId); } - @PreAuthorize("@taskAuthorizationService.canCallFinish(#auth.getPrincipal(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallFinish(#taskId)") @Operation(summary = "Finish task", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -119,11 +119,11 @@ public EntityModel<EventOutcomeWithMessage> delegate(Authentication auth, @PathV @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), }) public EntityModel<EventOutcomeWithMessage> finish(Authentication auth, @PathVariable("id") String taskId) { - LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); - return super.finish(loggedUser, taskId); + LoggedIdentity identity = (LoggedIdentity) auth.getPrincipal(); + return super.finish(identity, taskId); } - @PreAuthorize("@taskAuthorizationService.canCallCancel(#auth.getPrincipal(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallCancel(#taskId)") @Operation(summary = "Cancel task", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -133,19 +133,19 @@ public EntityModel<EventOutcomeWithMessage> finish(Authentication auth, @PathVar @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), }) public EntityModel<EventOutcomeWithMessage> cancel(Authentication auth, @PathVariable("id") String taskId) { - LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); - return super.cancel(loggedUser, taskId); + LoggedIdentity identity = (LoggedIdentity) auth.getPrincipal(); + return super.cancel(identity, taskId); } @Override - @Operation(summary = "Get all tasks assigned to logged user", security = {@SecurityRequirement(name = "BasicAuth")}) + @Operation(summary = "Get all tasks assigned to actor", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/my", produces = MediaTypes.HAL_JSON_VALUE) public PagedModel<TaskResource> getMy(Authentication auth, Pageable pageable, PagedResourcesAssembler<Task> assembler, Locale locale) { return super.getMy(auth, pageable, assembler, locale); } @Override - @Operation(summary = "Get all finished tasks by logged user", security = {@SecurityRequirement(name = "BasicAuth")}) + @Operation(summary = "Get all finished tasks by actor", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/my/finished", produces = MediaTypes.HAL_JSON_VALUE) public PagedModel<TaskResource> getMyFinished(Pageable pageable, Authentication auth, PagedResourcesAssembler<Task> assembler, Locale locale) { return super.getMyFinished(pageable, auth, assembler, locale); @@ -172,6 +172,8 @@ public CountResponse count(@RequestBody SingleElasticTaskSearchRequestAsList que return super.count(query, operation, auth, locale); } + // TODO: NAE-1969 fix + @PreAuthorize("@taskAuthorizationService.canCallGetData(#taskId)") @Override @Operation(summary = "Get all task data", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/{id}/data", produces = MediaTypes.HAL_JSON_VALUE) @@ -180,7 +182,7 @@ public EntityModel<EventOutcomeWithMessage> getData(@PathVariable("id") String t return super.getData(taskId, locale, auth); } - @PreAuthorize("@taskAuthorizationService.canCallSaveData(#auth.getPrincipal(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallSetData(#taskId)") @Operation(summary = "Set task data", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -193,7 +195,7 @@ public EntityModel<EventOutcomeWithMessage> setData(Authentication auth, @PathVa return super.setData(taskId, dataBody, auth); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#taskId)") @Operation(summary = "Upload file into the task", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -212,7 +214,7 @@ public ResponseEntity<Resource> getFile(@PathVariable("id") String taskId, @Requ return super.getFile(taskId, fieldId); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#taskId)") @Operation(summary = "Remove file from the task", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -225,7 +227,7 @@ public EntityModel<EventOutcomeWithMessage> deleteFile(Authentication auth, @Pat return super.deleteFile(requestBody.getParentTaskId(), requestBody.getFieldId()); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#taskId)") @Operation(summary = "Upload multiple files into the task", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -244,7 +246,7 @@ public ResponseEntity<Resource> getNamedFile(@PathVariable("id") String taskId, return super.getNamedFile(taskId, fieldId, fileName); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#taskId)") @Operation(summary = "Remove file from tasks file list field value", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index 628fa7e3fa9..d39e44c0763 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -1,15 +1,17 @@ package com.netgrif.application.engine.workflow.web; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.elastic.domain.ElasticCase; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.web.requestbodies.singleaslist.SingleCaseSearchRequestAsList; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.MergeFilterOperation; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.DeleteCaseEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessage; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessageResource; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.DeleteCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response.EventOutcomeWithMessage; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response.EventOutcomeWithMessageResource; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.DeleteCaseParams; import com.netgrif.application.engine.workflow.service.FileFieldInputStream; import com.netgrif.application.engine.workflow.service.interfaces.IDataService; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; @@ -55,7 +57,7 @@ havingValue = "true", matchIfMissing = true ) -@Tag(name = "Workflow") +@Tag(name = "Workflow Controller") public class WorkflowController { private final IWorkflowService workflowService; @@ -70,14 +72,20 @@ public WorkflowController(IWorkflowService workflowService, ITaskService taskSer this.dataService = dataService; } - @PreAuthorize("@workflowAuthorizationService.canCallCreate(#auth.getPrincipal(), #body.netId)") + @PreAuthorize("@caseAuthorizationService.canCallCreate(#body.netId)") @Operation(summary = "Create new case", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/case", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public EntityModel<EventOutcomeWithMessage> createCase(@RequestBody CreateCaseBody body, Authentication auth, Locale locale) { - LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); + LoggedIdentity identity = (LoggedIdentity) auth.getPrincipal(); try { - CreateCaseEventOutcome outcome = workflowService.createCase(body.netId, body.title, body.color, loggedUser, locale); - return EventOutcomeWithMessageResource.successMessage("Case with id " + outcome.getCase().getStringId() + " was created succesfully", outcome); + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processId(body.netId) + .title(body.title) + .authorId(identity.getActiveActorId()) + .locale(locale) + .build(); + CreateCaseEventOutcome outcome = workflowService.createCase(createCaseParams); + return EventOutcomeWithMessageResource.successMessage("Case with id " + outcome.getCase().getStringId() + " was created successfully", outcome); } catch (Exception e) { // TODO: 5. 2. 2017 change to custom exception log.error("Creating case failed:", e); return EventOutcomeWithMessageResource.errorMessage("Creating case failed" + e.getMessage()); @@ -110,8 +118,8 @@ public PagedModel<CaseResource> search2(@QuerydslPredicate(root = Case.class) Pr @Operation(summary = "Generic case search on Elasticsearch database", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/case/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public PagedModel<CaseResource> search(@RequestBody SingleCaseSearchRequestAsList searchBody, @RequestParam(defaultValue = "OR") MergeFilterOperation operation, Pageable pageable, PagedResourcesAssembler<Case> assembler, Authentication auth, Locale locale) { - LoggedUser user = (LoggedUser) auth.getPrincipal(); - Page<Case> cases = elasticCaseService.search(searchBody.getList(), user, pageable, locale, operation == MergeFilterOperation.AND); + LoggedIdentity identity = (LoggedIdentity) auth.getPrincipal(); + Page<Case> cases = elasticCaseService.search(searchBody.getList(), identity.getActiveActorId(), pageable, locale, operation == MergeFilterOperation.AND); Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(WorkflowController.class) .search(searchBody, operation, pageable, assembler, auth, locale)).withRel("search"); @@ -124,7 +132,8 @@ public PagedModel<CaseResource> search(@RequestBody SingleCaseSearchRequestAsLis @Operation(summary = "Get count of the cases", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/case/count", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public CountResponse count(@RequestBody SingleCaseSearchRequestAsList searchBody, @RequestParam(defaultValue = "OR") MergeFilterOperation operation, Authentication auth, Locale locale) { - long count = elasticCaseService.count(searchBody.getList(), (LoggedUser) auth.getPrincipal(), locale, operation == MergeFilterOperation.AND); + LoggedIdentity identity = (LoggedIdentity) auth.getPrincipal(); + long count = elasticCaseService.count(searchBody.getList(), identity.getActiveActorId(), locale, operation == MergeFilterOperation.AND); return CountResponse.caseCount(count); } @@ -148,9 +157,9 @@ public PagedModel<CaseResource> findAllByAuthor(@PathVariable("id") String autho return resources; } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@applicationAuthorizationService.hasApplicationRole('admin')") @Operation(summary = "Reload tasks of case", - description = "Caller must have the ADMIN role", + description = "Caller must have the admin role", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/case/reload/{id}", produces = MediaTypes.HAL_JSON_VALUE) @ApiResponses(value = { @@ -170,7 +179,7 @@ public MessageResource reloadTasks(@PathVariable("id") String caseId) { } } - @PreAuthorize("@workflowAuthorizationService.canCallDelete(#auth.getPrincipal(), #caseId)") + @PreAuthorize("@caseAuthorizationService.canCallDelete(#caseId)") @Operation(summary = "Delete case", security = {@SecurityRequirement(name = "BasicAuth")}) @DeleteMapping(value = "/case/{id}", produces = MediaTypes.HAL_JSON_VALUE) public EntityModel<EventOutcomeWithMessage> deleteCase(Authentication auth, @PathVariable("id") String caseId, @RequestParam(defaultValue = "false") boolean deleteSubtree) { @@ -179,7 +188,7 @@ public EntityModel<EventOutcomeWithMessage> deleteCase(Authentication auth, @Pat if (deleteSubtree) { outcome = workflowService.deleteSubtreeRootedAt(caseId); } else { - outcome = workflowService.deleteCase(caseId); + outcome = workflowService.deleteCase(new DeleteCaseParams(caseId)); } return EventOutcomeWithMessageResource.successMessage("Case " + caseId + " was deleted", outcome); } diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/requestbodies/TaskSearchRequest.java b/src/main/java/com/netgrif/application/engine/workflow/web/requestbodies/TaskSearchRequest.java index b205d45681a..cf76f69913e 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/requestbodies/TaskSearchRequest.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/requestbodies/TaskSearchRequest.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; +import com.netgrif.application.engine.workflow.domain.State; import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.PetriNet; import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.TaskSearchCaseRequest; import lombok.AllArgsConstructor; @@ -14,6 +15,8 @@ @AllArgsConstructor public class TaskSearchRequest { + // todo: release/8.0.0 update + @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public List<String> role; @@ -25,7 +28,7 @@ public class TaskSearchRequest { public List<String> title; @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) - public List<String> user; + public List<String> assigneeId; @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public List<PetriNet> process; @@ -36,13 +39,10 @@ public class TaskSearchRequest { public String fullText; @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) - public List<String> group; - - @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) - public List<String> users; + public List<String> stringId; @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) - public List<String> stringId; + public List<State> state; - public Map<String, String> tags; + public Map<String, String> properties; } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/DataFieldReference.java b/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/DataFieldReference.java index c810b84eef4..badf6897e60 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/DataFieldReference.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/DataFieldReference.java @@ -22,6 +22,6 @@ public DataFieldReference(String stringId, String title, DataType type) { } public DataFieldReference(Field<?> field, Locale locale) { - this(field.getStringId(), field.getTranslatedName(locale), field.getType()); + this(field.getStringId(), field.getTranslatedTitle(locale), field.getType()); } } diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/ElasticTaskResourceAssembler.java b/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/ElasticTaskResourceAssembler.java index e5ddd547892..c2e4ad5da2e 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/ElasticTaskResourceAssembler.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/ElasticTaskResourceAssembler.java @@ -16,8 +16,9 @@ public TaskResource toModel(ElasticTask entity) { .caseId(entity.getCaseId()) .transitionId(entity.getTransitionId()) .title(new I18nString(entity.getTitle())) - .caseTitle(entity.getCaseTitle()) - .priority(entity.getPriority()) +// TODO: release/8.0.0 +// .caseTitle(entity.getCaseTitle()) +// .priority(entity.getPriority()) .build(); return new TaskResource(taskModel); } diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/Filter.java b/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/Filter.java index d99a5a8f3b3..a03e5d12ccd 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/Filter.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/Filter.java @@ -1,7 +1,7 @@ package com.netgrif.application.engine.workflow.web.responsebodies; import com.fasterxml.jackson.annotation.JsonRootName; -import com.netgrif.application.engine.auth.domain.Author; +import com.netgrif.application.engine.authorization.domain.User; import com.netgrif.application.engine.workflow.domain.MergeFilterOperation; import lombok.Data; @@ -24,7 +24,7 @@ public class Filter { private Integer visibility; - private Author author; + private User author; // todo: release/8.0.0 Actor type leads to compilation error private LocalDateTime created; diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/TaskDataSets.java b/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/TaskDataSets.java index dd47c1b2065..240c29d11c0 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/TaskDataSets.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/TaskDataSets.java @@ -10,7 +10,9 @@ @AllArgsConstructor @NoArgsConstructor public class TaskDataSets { - + /** + * Key is taskId, value is DataSet + * */ private Map<String, DataSet> body; } diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/TaskResource.java b/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/TaskResource.java index 0ab75dadfe0..b60b1ae8678 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/TaskResource.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/TaskResource.java @@ -31,8 +31,9 @@ private void buildLinks() { .finish((Authentication) null, task.getStringId())).withRel("finish")); add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(TaskController.class) .cancel((Authentication) null, task.getStringId())).withRel("cancel")); - add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(TaskController.class) - .getData(task.getStringId(), null, null)).withRel("data")); + // TODO: NAE-1969 fix +// add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(TaskController.class) +// .getData(task.getStringId(), null, null)).withRel("data")); add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(TaskController.class) .setData((Authentication) null, task.getStringId(), null)).withRel("data-edit")); try { diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 65eacce38f7..a98603eacf6 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -21,7 +21,7 @@ spring.servlet.multipart.max-request-size=50MB nae.uri.index=${DATABASE_NAME:nae}_uri # MongoDB -spring.data.mongodb.uri=${MONGO_URI:mongodb://localhost:27017} +spring.data.mongodb.uri=${MONGO_URI:mongodb://localhost:27017/?replicaSet=rs0} #spring.data.mongodb.host=${MONGO_HOST:localhost} #spring.data.mongodb.port=${MONGO_PORT:27017} spring.data.mongodb.database=${DATABASE_NAME:nae} @@ -101,6 +101,7 @@ nae.security.jwt.private-key=file:src/main/resources/certificates/private.der nae.security.server-patterns=/api/auth/signup,/api/auth/token/verify,/api/auth/reset,/api/auth/recover,/api/public/**,/v3/api-docs/public nae.security.anonymous-exceptions=/api/auth/signup,/api/auth/token/verify,/api/auth/reset,/api/auth/recover springdoc.swagger-ui.enabled=false +nae.public.strategy=advanced # Quartz (this config overwrites quartz.properties resource file) org.quartz.jobStore.mongoUri=${MONGO_URI:mongodb://localhost:27017} @@ -158,14 +159,6 @@ nae.ldap.groupSearchBase=ou=groups nae.ldap.peopleClass=inetOrgPerson,person #nae.ldap.mapHomeDirectory=displayName -# Impersonation -nae.impersonation.redis-namespace=${DATABASE_NAME:nae}:impersonation:impersonator -nae.impersonation.enabled=${IMPERSONATION_ENABLED:true} - -#Groups -nae.group.defaultEnabled=true -nae.group.systemEnabled=true - # Image preview scaling nae.image.preview.scaling.px=400 nae.validation.setData.enable=false @@ -181,3 +174,27 @@ nae.filter.export.file-name=filters.xml nae.actions.imports=com.netgrif.application.engine.workflow.web.responsebodies.DataSet nae.actions.star-imports=java.time,com.netgrif.application.engine.petrinet.domain.dataset,com.netgrif.application.engine.petrinet.domain,com.netgrif.application.engine.auth.domain nae.actions.static-star-imports=java.time.LocalDate + +# LAYOUT CONFIGURATION FLEX LAYOUT ROOT +nae.layout.flex.root.display=flex +nae.layout.flex.root.flex-direction=column +nae.layout.flex.root.justify-content=flex-start +nae.layout.flex.root.align-items=stretch + +# LAYOUT CONFIGURATION FLEX LAYOUT CONTAINER +nae.layout.flex.container.display=flex +nae.layout.flex.container.flex-direction=row +nae.layout.flex.container.justify-content=space-between +nae.layout.flex.container.align-items=stretch + +# LAYOUT CONFIGURATION FLEX LAYOUT CHILDREN +nae.layout.flex.children.flex-grow=1 +nae.layout.flex.children.flex-basis=0 + +# LAYOUT CONFIGURATION GRID LAYOUT ROOT +nae.layout.grid.root.display=grid +nae.layout.grid.root.grid-template-columns=repeat(2, 1fr) +nae.layout.grid.root.justify-items=stretch +nae.layout.grid.root.align-items=stretch +nae.layout.grid.root.justify-content=stretch +nae.layout.grid.root.align-content=stretch diff --git a/src/main/resources/petriNets/FM_v0_2.xml b/src/main/resources/petriNets/FM_v0_2.xml deleted file mode 100644 index e6620e07125..00000000000 --- a/src/main/resources/petriNets/FM_v0_2.xml +++ /dev/null @@ -1,6354 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document> - <id>examples/FM/fm_archivacia</id> - <title>FM Archivácia - FM - Archivácia - - - 1 - FM worker - - - 2 - FM manager - - - 3 - Client - - - 4 - Client manager - - - 5 - FM courier - - - 6 - Supplier - - - 7 - System - - - - - 1 - Box - - - 2 - Ukl. jednotka - - - 3 - Čísla spisov - - - 4 - Vecný obsah UJ - - - 5 - Od (rok) - - - 6 - Do (rok) - - - 7 - Firma - - - 8 - Oddelenie - - - 9 - Odovzdávajúci - 1 - 2 - - - 10 - Dátum odovzdania - - - 11 - Forma - - - 12 - Lehota uloženia - - - 13 - Znak hodnoty - - - 14 - Čiarový kód - - - 15 - Lokalizácia - - - 16 - Poznámka - - - 17 - Číslo plomby - - - 18 - Nový dátum skartácie - - - 19 - Dátum vypožičania - - - 20 - Dátum vrátenia - - - 21 - Vypožičal - 1 - 2 - - - 22 - Vrátil - 1 - 2 - - - 23 - Názov UJ na scan - - - 24 - Sporná vec - - - 25 - Typ dokumentu - - - 26 - Rok uloženia - - - 27 - Registratúrna značka - - - 28 - Poznámka - - - 29 - Číslo protokolu - - - 30 - Klientské číslo - - - 31 - Odovzdal - 1 - 2 - - - 32 - Počet škatúľ - - - 33 - Kuriér - 1 - 2 - - - 34 - Spracoval - 1 - 2 - - - 35 - Číselný rozsah spracovaných škatúľ - - - - 36 - Počet uvedený v systéme - - - 37 - Založil - 1 - 2 - - - 38 - Zapísal do systému - 1 - 2 - - - 39 - Navrhované miesto odovzdania - - - 40 - Navrhovaný dátum odovzdania - - - 41 - Scan - - - 42 - Akceptovanie termínu a miesta odovzdania - - - 43 - Dôvod zrušenia - - - 44 - Predpokladaný počet škatúľ - - - 45 - Čas stretnutia - - - 46 - Pin kód - - - 47 - Povoliť sprístupnenie klientovi? - - - 48 - Dátum skartácie - - - - 1 - 56 - 222 - - - 3 - - true - - - - 4 - - true - true - - - - 1 - - editable - - - - 2 - - editable - - - - 3 - - editable - - - - 4 - - editable - - - - 5 - - editable - - - - 6 - - editable - - - - 7 - - editable - - - - 8 - - editable - - - - 9 - - editable - - - - 10 - - editable - - - - 11 - - editable - - - - 12 - - editable - - - - 13 - - editable - - - - 14 - - editable - - - - 15 - - editable - - - - 16 - - editable - - - - 17 - - editable - - - - - 2 - 216 - 578 - - - 1 - - true - - - - 2 - - true - true - - - - 30 - - editable - - - - 44 - - editable - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 10 - 223 - 368 - - - 3 - - true - - - - 4 - - true - true - - - - 30 - - editable - - - - 32 - - editable - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 13 - 297 - 136 - - - 3 - - true - - - - 4 - - true - true - - - - 15 - - editable - - - - 19 - - visible - - - - 21 - - visible - - - - 20 - - editable - - - - 22 - - editable - - - - - 19 - 167 - 136 - - - 3 - - true - - - - 4 - - true - true - - - - 15 - - editable - - - - 19 - - editable - - - - 21 - - editable - - - - - 23 - 660 - 460 - - - 5 - - true - - - - 2 - - true - true - - - - 42 - - editable - - - - 30 - - visible - - - - 44 - - visible - - - - 32 - - visible - - - - 39 - - visible - - - - 40 - - visible - - - - 45 - - visible - - - - - 26 - 535 - 506 - - - 5 - - true - - - - 2 - - true - true - - - - 30 - - visible - - - - 44 - - visible - - - - 32 - - visible - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 31 - 534 - 626 - - - 3 - - true - - - - 4 - - true - true - - - - 30 - - visible - - - - 44 - - visible - - - - 32 - - visible - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 36 - 1012 - 580 - - - 3 - - true - - - - 4 - - true - true - - - - 30 - - visible - - - - 32 - - editable - - - - 31 - - editable - - - - 39 - - visible - - - - 31 - - visible - - - - 45 - - editable - - - - - - 39 - 1190 - 418 - - - 1 - - true - - - - 2 - - true - true - - - - 1 - - editable - - - - 2 - - editable - - - - 3 - - editable - - - - 4 - - editable - - - - 5 - - editable - - - - 6 - - editable - - - - 7 - - editable - - - - 8 - - editable - - - - 9 - - editable - - - - 10 - - editable - - - - 11 - - editable - - - - 12 - - editable - - - - 13 - - editable - - - - 14 - - editable - - - - 15 - - editable - - - - 16 - - editable - - - - 17 - - editable - - - - - 42 - 937 - 231 - - - 1 - - true - - - - 2 - - true - true - - - - 16 - - editable - - - - 2 - - visible - - - - - 45 - 725 - 315 - - - 3 - - true - - - - 4 - - true - true - - - - 16 - - editable - - - - 2 - - visible - - - - - 51 - 1884 - 598 - - - 30 - - editable - - - - 2 - - editable - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 52 - 2741 - 761 - - - 5 - - true - - - - 2 - - true - true - - - - 30 - - visible - - - - 2 - - visible - - - - 31 - - editable - - - - 39 - - visible - - - - 31 - - visible - - - - 45 - - editable - - - - - - 66 - 2747 - 967 - - - 3 - - true - - - - 4 - - true - true - - - - 30 - - visible - - - - 2 - - visible - - - - 21 - - editable - - - - 39 - - visible - - - - 31 - - visible - - - - 45 - - editable - - - - - - 67 - 1800 - 1172 - - - 3 - - true - - - - 4 - - true - true - - - - 30 - - visible - - - - 2 - - visible - - - - 21 - - visible - - - - 39 - - visible - - - - 31 - - visible - - - - 45 - - editable - - - - - 68 - 1793 - 791 - - - 1 - - true - - - - 2 - - true - true - - - - 30 - - visible - - - - 2 - - visible - - - - 20 - - editable - - - - 34 - - - editable - - - - - 122 - 1685 - 301 - - - 3 - - true - - - - 4 - - true - true - - - - 2 - - editable - - - - 3 - - editable - - - - 7 - - editable - - - - 8 - - editable - - - - 16 - - editable - - - - 23 - - editable - - - - - 125 - 1534 - 390 - - - 3 - - true - - - - 4 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 16 - - editable - - - - 23 - - visible - - - - 41 - - editable - - - - 34 - - editable - - - - - 181 - 165 - 899 - - - 1 - - true - - - - 2 - - true - true - - - - 1 - - - visible - - - - 2 - - visible - - - - 3 - - visible - - - - 4 - - visible - - - - 5 - - visible - - - - 6 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 9 - - visible - - - - 10 - - visible - - - - 11 - - visible - - - - 12 - - visible - - - - 13 - - visible - - - - 14 - - visible - - - - 15 - - visible - - - - 16 - - visible - - - - 17 - - visible - - - - 18 - - visible - - - - 19 - - visible - - - - 20 - - visible - - - - 21 - - visible - - - - 22 - - visible - - - - 23 - - visible - - - - 24 - - visible - - - - 25 - - visible - - - - 26 - - visible - - - - 27 - - visible - - - - 28 - - visible - - - - 29 - - visible - - - - 30 - - visible - - - - 31 - - visible - - - - 32 - - visible - - - - 33 - - visible - - - - 34 - - visible - - - - 35 - - visible - - - - 36 - - visible - - - - 37 - - visible - - - - 38 - - visible - - - - 39 - - visible - - - - 40 - - visible - - - - 41 - - visible - - - - 42 - - visible - - - - 43 - - visible - - - - 44 - - visible - - - - 45 - - visible - - - - - 242 - 1198 - 589 - - - 1 - - true - - - - 2 - - true - true - - - - 1 - - editable - - - - 2 - - editable - - - - 3 - - editable - - - - 4 - - editable - - - - 5 - - editable - - - - 6 - - editable - - - - 7 - - editable - - - - 8 - - editable - - - - 9 - - editable - - - - 10 - - editable - - - - 11 - - editable - - - - 12 - - editable - - - - 13 - - editable - - - - 14 - - editable - - - - 15 - - editable - - - - 16 - - editable - - - - 17 - - editable - - - - - 494 - 812 - 504 - - - 5 - - true - - - - 2 - - true - true - - - - 30 - - visible - - - - 44 - - visible - - - - 32 - - visible - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 497 - 1025 - 684 - - - 5 - - true - - - - 2 - - true - true - - - - 30 - - visible - - - - 44 - - visible - - - - 32 - - visible - - - - 39 - - visible - - - - 40 - - visible - - - - 45 - - visible - - - - 43 - - editable - - - - - 503 - 1093 - 506 - - - 5 - - true - - - - 2 - - true - true - - - - 30 - - visible - - - - 32 - - editable - - - - 31 - - visible - - - - 39 - - visible - - - - 31 - - visible - - - - 45 - - visible - - - - 33 - - editable - - - - 46 - - editable - - - - - - 587 - 2099 - 706 - - - 5 - - true - - - - 2 - - true - true - - - - 30 - - visible - - - - 2 - - visible - - - - 39 - - editable - - - - 31 - - editable - - - - 45 - - editable - - - - - 588 - 2095 - 818 - - - 3 - - true - - - - 4 - - true - true - - - - 30 - - visible - - - - 2 - - visible - - - - 39 - - editable - - - - 31 - - editable - - - - 45 - - editable - - - - - 597 - 2422 - 1071 - - - 1 - - true - - - - 2 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 19 - - visible - - - - 21 - - visible - - - - 24 - - editable - - - - - 598 - 2421 - 997 - - - 3 - - true - - - - 4 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 19 - - visible - - - - 21 - - visible - - - - 24 - - editable - - - - - 614 - 2752 - 1241 - - - 3 - - true - - - - 4 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 19 - - visible - - - - 21 - - visible - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 618 - 2451 - 1296 - - - 3 - - true - - - - 4 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 19 - - visible - - - - 21 - - visible - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 619 - 2455 - 1178 - - - 5 - - true - - - - 2 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 19 - - visible - - - - 21 - - visible - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 626 - 1994 - 998 - - - 3 - - true - - - - 4 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 19 - - visible - - - - 21 - - visible - - - - 24 - - editable - - - - - 627 - 1996 - 1065 - - - 1 - - true - - - - 2 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 19 - - visible - - - - 21 - - visible - - - - 24 - - editable - - - - - 729 - 815 - 628 - - - 3 - - true - - - - 4 - - true - true - - - - 42 - - editable - - - - 30 - - visible - - - - 44 - - visible - - - - 32 - - visible - - - - 39 - - visible - - - - 40 - - visible - - - - 45 - - visible - - - - - 733 - 660 - 700 - - - 3 - - true - - - - 4 - - true - true - - - - 30 - - visible - - - - 44 - - visible - - - - 32 - - visible - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 744 - 1356 - 635 - - - 3 - - true - - - - 4 - - true - - - - 1 - - - editable - - - - 2 - - editable - - - - 3 - - editable - - - - 4 - - editable - - - - 5 - - editable - - - - 6 - - editable - - - - 7 - - editable - - - - 8 - - editable - - - - 9 - - editable - - - - 10 - - editable - - - - 11 - - editable - - - - 12 - - editable - - - - 13 - - editable - - - - 14 - - editable - - - - 15 - - editable - - - - 16 - - editable - - - - 17 - - editable - - - - - 748 - 1427 - 499 - - - 1 - - true - - - - 2 - - true - true - - - - 14 - - editable - - - - 15 - - editable - - - - 16 - - editable - - - - 7 - - visible - - - - 1 - - - editable - - - - 2 - - visible - - - - 3 - - visible - - - - - - 753 - 1794 - 340 - - - 3 - - true - - - - 4 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 757 - 1642 - 498 - - - 1 - - true - - - - 2 - - true - true - - - - 1 - - - editable - - - - 2 - - editable - - - - 3 - - editable - - - - 4 - - editable - - - - 5 - - editable - - - - 6 - - editable - - - - 7 - - editable - - - - 8 - - editable - - - - 9 - - editable - - - - 10 - - editable - - - - 11 - - editable - - - - 12 - - editable - - - - 13 - - editable - - - - 14 - - editable - - - - 15 - - editable - - - - 16 - - editable - - - - 17 - - editable - - - - - 763 - 1532 - 635 - - - 1 - - true - - - - 2 - - true - true - - - - 2 - - editable - - - - 47 - - editable - - - - - 768 - 1199 - 784 - - - 1 - - true - - - - 2 - - true - true - - - - 1 - - - editable - - - - 2 - - editable - - - - 3 - - editable - - - - 4 - - editable - - - - 5 - - editable - - - - 6 - - editable - - - - 7 - - editable - - - - 8 - - editable - - - - 9 - - editable - - - - 10 - - editable - - - - 11 - - editable - - - - 12 - - editable - - - - 13 - - editable - - - - 14 - - editable - - - - 15 - - editable - - - - 16 - - editable - - - - 17 - - editable - - - - - 773 - 60 - 44 - - - 3 - - true - - - - 4 - - true - true - - - - 1 - - - visible - - - - 2 - - visible - - - - 3 - - visible - - - - 4 - - visible - - - - 5 - - visible - - - - 6 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 9 - - visible - - - - 10 - - visible - - - - 11 - - visible - - - - 12 - - visible - - - - 13 - - visible - - - - 14 - - visible - - - - 15 - - visible - - - - 16 - - visible - - - - 17 - - visible - - - - - 914 - 2215 - 203 - - - 5 - - true - - - - 2 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 39 - - visible - - - - 40 - - visible - - - - 45 - - visible - - - - 42 - - editable - - - - - 915 - 2383 - 393 - - - 3 - - true - - - - 4 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 39 - - visible - - - - 40 - - visible - - - - 45 - - visible - - - - 42 - - editable - - - - - 916 - 2049 - 273 - - - 5 - - true - - - - 2 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 917 - 2386 - 275 - - - 5 - - true - - - - 2 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 918 - 2207 - 450 - - - 3 - - true - - - - 4 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 39 - - editable - - - - 40 - - editable - - - - 45 - - editable - - - - - 919 - 2666 - 510 - - - 3 - - true - - - - 4 - - true - true - - - - 2 - - visible - - - - 3 - - visible - - - - 7 - - visible - - - - 8 - - visible - - - - 15 - - visible - - - - 39 - - visible - - - - 40 - - visible - - - - 45 - - visible - - - - 43 - - editable - - - - - 920 - 2675 - 371 - - - 5 - - true - - - - 2 - - true - true - - - - - 921 - 2667 - 220 - - - 3 - - true - - - - 4 - - true - true - - - - - 922 - 2382 - 136 - - - 1 - - true - - - - 2 - - true - true - - - - - 923 - 2384 - 63 - - - 3 - - true - - - - 4 - - true - true - - - - - 959 - 2667 - 23 - - - 3 - - true - - - - 4 - - true - true - - - - - 962 - 2667 - 593 - - - 5 - - true - - - - 2 - - true - true - - - - - 981 - 2057 - 389 - - - 3 - - true - - - - 4 - - true - true - - - - - 1146 - 2241 - 1131 - - - 5 - - true - - - - 2 - - true - true - - - - - 1148 - 1806 - 1312 - - - 5 - - true - - - - 2 - - true - true - - - - - 1149 - 2441 - 707 - - - 5 - - true - - - - 2 - - true - true - - - - - 1153 - 2096 - 1298 - - - 3 - - true - - - - 4 - - true - true - - - - - 1154 - 2244 - 1369 - - - 3 - - true - - - - 4 - - true - true - - - - - 1155 - 2441 - 822 - - - 3 - - true - - - - 4 - - true - true - - - - - 1156 - 2277 - 905 - - - 3 - - true - - - - 4 - - true - true - - - - - 1160 - 2270 - 649 - - - 5 - - true - - - - 2 - - true - true - - - - - 1162 - 2104 - 1177 - - - 5 - - true - - - - 2 - - true - true - - - - - 1233 - 1399 - 1016 - - - 3 - - true - - - - 4 - - true - true - - - - - 1234 - 1596 - 863 - - - 3 - - true - - - - 4 - - true - true - - - - - 1236 - 1178 - 1016 - - - 1 - - true - - - - 2 - - true - true - - - - - 1237 - 544 - 1439 - - - 1 - - true - - - - 2 - - true - true - - - - - 1238 - 1574 - 1420 - - - 5 - - true - - - - 2 - - true - true - - - - - 1239 - 435 - 1303 - - - 1 - - true - - - - 2 - - true - true - - - - - 1240 - 2032 - 1565 - - - 1 - - true - - - - 2 - - true - true - - - - - 1241 - 944 - 1016 - - - 1 - - true - - - - 2 - - true - true - - - - - 1242 - 435 - 1016 - - - 1 - - true - - - - 2 - - true - true - - - - - 1243 - 1715 - 1565 - - - 1 - - true - - - - 2 - - true - true - - - - - 1244 - 1388 - 890 - - - 1 - - true - - - - 2 - - true - true - - - - - 1281 - 1605 - 1124 - - - 1 - - true - - - - 2 - - true - true - - - - - 1282 - 771 - 1124 - - - 1 - - true - - - - 2 - - true - true - - - - - 1507 - 1206 - 1492 - - - 5 - - true - - - - 2 - - true - true - - - - - 1512 - 1046 - 1563 - - - 5 - - true - - - - 2 - - true - true - - - - - 1513 - 1208 - 1367 - - - 6 - - true - true - - - - - 1514 - 1050 - 1643 - - - 1 - - true - - - - 2 - - true - true - - - - - 1520 - 869 - 1367 - - - 5 - - true - - - - 2 - - true - true - - - - - 1521 - 870 - 1489 - - - 6 - - true - true - - - - - 1530 - 1038 - 1293 - - - - - 0 - 58 - 578 - - 1 - false - - - 8 - 226 - 220 - - 0 - false - - - 14 - 234 - 75 - - 0 - false - - - 22 - 380 - 580 - - 0 - false - - - 29 - 660 - 580 - - 0 - false - - - 34 - 940 - 580 - - 0 - false - - - 38 - 1092 - 419 - - 0 - false - - - 44 - 722 - 229 - - 0 - false - - - 49 - 1794 - 502 - - 0 - false - - - 53 - 1960 - 769 - - 0 - false - - - 69 - 2745 - 866 - - 0 - false - - - 75 - 1797 - 999 - - 0 - false - - - 124 - 1533 - 299 - - 0 - false - - - 237 - 446 - 369 - - 0 - false - - - 240 - 1092 - 786 - - 0 - false - - - 504 - 1011 - 505 - - 0 - false - - - 593 - 2609 - 762 - - 0 - false - - - 599 - 2261 - 999 - - 0 - false - - - 602 - 2748 - 1069 - - 0 - false - - - 616 - 2632 - 1239 - - 0 - false - - - 620 - 2274 - 1243 - - 0 - false - - - 628 - 2157 - 995 - - 0 - false - - - 742 - 1437 - 635 - - 0 - false - - - 747 - 1309 - 500 - - 0 - false - - - 759 - 1543 - 498 - - 0 - false - - - 762 - 1531 - 562 - - 0 - false - - - 767 - 1201 - 692 - - 0 - false - - - 772 - 57 - 146 - - 0 - false - - - 913 - 2673 - 296 - - 0 - false - - - 925 - 1993 - 61 - - 0 - false - - - 926 - 2544 - 368 - - 0 - false - - - 927 - 2217 - 356 - - 0 - false - - - 928 - 2667 - 139 - - 0 - false - - - 932 - 1889 - 340 - - 0 - false - - - 1171 - 2279 - 769 - - 0 - false - - - 1177 - 1977 - 1237 - - 0 - false - - - 1246 - 2182 - 1565 - - 0 - false - - - 1247 - 1528 - 1016 - - 0 - false - - - 1248 - 1073 - 1016 - - 0 - false - - - 1249 - 435 - 1188 - - 0 - false - - - 1250 - 696 - 1439 - - 0 - false - - - 1251 - 1867 - 1565 - - 0 - false - - - 1252 - 1578 - 1569 - - 0 - false - - - 1253 - 1280 - 1016 - - 0 - false - - - 1254 - 772 - 1016 - - 0 - false - - - 1255 - 435 - 1439 - - 0 - false - - - 1286 - 1208 - 1124 - - 0 - false - - - 1508 - 1397 - 1423 - - 0 - false - - - 1519 - 1046 - 1431 - - 0 - false - - - - - 9 - regular - 1 - 8 - 1 - - - 11 - regular - 8 - 10 - 1 - - - 17 - regular - 14 - 13 - 1 - - - 18 - regular - 13 - 8 - 1 - - - 20 - regular - 8 - 19 - 1 - - - 21 - regular - 19 - 14 - 1 - - - 24 - regular - 10 - 22 - 1 - - 221 - 516 - - - 345 - 519 - - - - 25 - regular - 22 - 23 - 1 - - 380 - 460 - - - - 27 - regular - 22 - 26 - 1 - - 426 - 505 - - - - 30 - regular - 26 - 29 - 1 - - 624 - 505 - - - - 32 - regular - 29 - 31 - 1 - - 623 - 625 - - - - 33 - regular - 31 - 22 - 1 - - 427 - 625 - - - - 35 - regular - 23 - 34 - 1 - - 940 - 460 - - - - 37 - regular - 34 - 36 - 1 - - - 41 - regular - 38 - 39 - 1 - - - 43 - regular - 38 - 42 - 1 - - - 46 - regular - 42 - 44 - 1 - - - 47 - regular - 44 - 45 - 1 - - - 48 - regular - 45 - 38 - 1 - - 876 - 318 - - - - 57 - regular - 49 - 51 - 1 - - - 58 - regular - 51 - 53 - 1 - - 1884 - 770 - - - - 71 - regular - 52 - 69 - 1 - - - 72 - regular - 69 - 66 - 1 - - - 76 - regular - 67 - 75 - 1 - - - 77 - regular - 75 - 68 - 1 - - - 78 - regular - 68 - 49 - 1 - - - 123 - regular - 49 - 122 - 1 - - - 126 - regular - 122 - 124 - 1 - - - 127 - regular - 124 - 125 - 1 - - - 128 - regular - 125 - 49 - 1 - - 1688 - 391 - - - - 238 - regular - 10 - 237 - 1 - - - 241 - regular - 2 - 240 - 1 - - 213 - 792 - - - - 244 - regular - 38 - 242 - 1 - - - 495 - regular - 34 - 494 - 1 - - 904 - 506 - - - - 505 - regular - 36 - 504 - 1 - - - 506 - regular - 504 - 503 - 1 - - - 507 - regular - 503 - 38 - 1 - - - 583 - regular - 240 - 242 - 1 - - - 584 - regular - 237 - 39 - 1 - - 447 - 182 - - - 1189 - 190 - - - - 595 - regular - 593 - 52 - 1 - - - 601 - regular - 599 - 597 - 1 - - 2261 - 1071 - - - - 603 - regular - 597 - 602 - 1 - - - 604 - regular - 602 - 598 - 1 - - 2589 - 997 - - - - 606 - regular - 598 - 599 - 1 - - 2288 - 997 - - - - 613 - regular - 66 - 602 - 1 - - - 615 - regular - 602 - 614 - 1 - - - 617 - regular - 614 - 616 - 1 - - - 630 - regular - 75 - 627 - 1 - - 1843 - 1065 - - - - 631 - regular - 627 - 628 - 1 - - 2156 - 1061 - - - - 632 - regular - 628 - 626 - 1 - - - 633 - regular - 626 - 75 - 1 - - - 730 - regular - 29 - 729 - 1 - - 703 - 627 - - - - 731 - regular - 729 - 34 - 1 - - 904 - 627 - - - - 732 - regular - 497 - 0 - 1 - - 1000 - 751 - - - 56 - 754 - - - - 734 - regular - 34 - 733 - 1 - - 940 - 700 - - - - 736 - regular - 494 - 29 - 1 - - 706 - 504 - - - - 737 - regular - 733 - 22 - 1 - - 380 - 700 - - - - 745 - regular - 742 - 744 - 1 - - - 746 - regular - 744 - 742 - 1 - - 1396 - 608 - - - - 749 - regular - 39 - 747 - 1 - - 1309 - 419 - - - - 750 - regular - 242 - 747 - 1 - - 1312 - 590 - - - - 751 - regular - 747 - 748 - 1 - - - 755 - regular - 49 - 753 - 1 - - - 761 - regular - 759 - 757 - 1 - - - 764 - regular - 757 - 762 - 1 - - - 765 - regular - 762 - 763 - 1 - - - 766 - regular - 763 - 742 - 1 - - - 769 - regular - 242 - 767 - 1 - - - 770 - regular - 767 - 768 - 1 - - - 771 - regular - 768 - 767 - 1 - - - 774 - regular - 1 - 772 - 1 - - - 775 - regular - 772 - 773 - 1 - - - 776 - regular - 773 - 772 - 1 - - 85 - 94 - - - - 908 - regular - 748 - 759 - 1 - - - 910 - regular - 757 - 49 - 1 - - - 935 - regular - 753 - 932 - 1 - - - 937 - regular - 932 - 914 - 1 - - 1891 - 202 - - - - 938 - regular - 932 - 916 - 1 - - 1921 - 272 - - - - 943 - regular - 926 - 920 - 1 - - - 944 - regular - 915 - 926 - 1 - - 2492 - 394 - - - - 948 - regular - 926 - 919 - 1 - - - 949 - regular - 927 - 915 - 1 - - 2252 - 392 - - - - 951 - regular - 920 - 913 - 1 - - - 952 - regular - 913 - 921 - 1 - - - 953 - regular - 919 - 49 - 1 - - - 954 - regular - 921 - 928 - 1 - - - 955 - regular - 928 - 923 - 1 - - 2617 - 65 - - - - 956 - regular - 923 - 925 - 1 - - - 957 - regular - 925 - 922 - 1 - - 1993 - 131 - - - - 958 - regular - 922 - 928 - 1 - - - 961 - regular - 959 - 8 - 1 - - 378 - 20 - - - 377 - 220 - - - - 971 - regular - 593 - 962 - 1 - - 2665 - 698 - - - - 972 - regular - 962 - 49 - 1 - - 1997 - 593 - - - - 973 - regular - 916 - 927 - 1 - - 2184 - 275 - - - - 976 - regular - 926 - 918 - 1 - - 2545 - 449 - - - - 977 - regular - 918 - 932 - 1 - - 1889 - 449 - - - - 978 - regular - 926 - 917 - 1 - - 2499 - 277 - - - - 980 - regular - 917 - 927 - 1 - - 2242 - 278 - - - - 982 - regular - 927 - 981 - 1 - - 2185 - 392 - - - - 983 - regular - 981 - 932 - 1 - - 1918 - 387 - - - - 1193 - regular - 53 - 1160 - 1 - - 1962 - 649 - - - - 1194 - regular - 1160 - 593 - 1 - - 2608 - 649 - - - - 1195 - regular - 53 - 587 - 1 - - 1986 - 706 - - - - 1196 - regular - 587 - 1171 - 1 - - 2224 - 706 - - - - 1197 - regular - 1171 - 1155 - 1 - - 2327 - 822 - - - - 1198 - regular - 1155 - 593 - 1 - - 2573 - 820 - - - - 1199 - regular - 593 - 1149 - 1 - - 2575 - 707 - - - - 1200 - regular - 1149 - 1171 - 1 - - 2314 - 707 - - - - 1201 - regular - 1171 - 588 - 1 - - 2227 - 820 - - - - 1203 - regular - 593 - 1156 - 1 - - 2610 - 907 - - - - 1204 - regular - 1156 - 53 - 1 - - 1963 - 906 - - - 1962 - 865 - - - - 1209 - regular - 616 - 619 - 1 - - 2577 - 1179 - - - - 1210 - regular - 619 - 620 - 1 - - 2313 - 1178 - - - - 1211 - regular - 620 - 1153 - 1 - - 2189 - 1298 - - - - 1212 - regular - 1153 - 1177 - 1 - - 2014 - 1296 - - - - 1213 - regular - 616 - 1146 - 1 - - 2572 - 1136 - - - - 1214 - regular - 1146 - 1177 - 1 - - 1981 - 1130 - - - - 1215 - regular - 1177 - 1154 - 1 - - 1977 - 1364 - - - - 1216 - regular - 1154 - 616 - 1 - - 2575 - 1374 - - - - 1217 - regular - 620 - 618 - 1 - - 2308 - 1296 - - - - 1218 - regular - 618 - 616 - 1 - - 2574 - 1295 - - - - 1219 - regular - 1177 - 1162 - 1 - - 2018 - 1176 - - - - 1220 - regular - 1162 - 620 - 1 - - 2202 - 1179 - - - - 1221 - regular - 1177 - 67 - 1 - - - 1223 - regular - 1148 - 602 - 1 - - 1807 - 1420 - - - 2819 - 1426 - - - 2815 - 1070 - - - - 1224 - regular - 240 - 497 - 1 - - - 1225 - regular - 34 - 497 - 1 - - - 1226 - regular - 0 - 2 - 1 - - - 1227 - regular - 2 - 22 - 1 - - - 1228 - regular - 0 - 1 - 1 - - - 1229 - regular - 914 - 926 - 1 - - 2539 - 205 - - - - 1230 - regular - 588 - 53 - 1 - - 1994 - 818 - - - - 1231 - regular - 1177 - 1148 - 1 - - - 1232 - regular - 928 - 959 - 1 - - 2667 - 97 - - - - 1256 - regular - 49 - 1234 - 1 - - - 1257 - regular - 1234 - 1247 - 1 - - - 1258 - regular - 1247 - 1233 - 1 - - - 1259 - regular - 1233 - 1253 - 1 - - - 1260 - regular - 1253 - 1236 - 1 - - - 1261 - regular - 1236 - 1248 - 1 - - - 1262 - regular - 1248 - 1241 - 1 - - - 1263 - regular - 1241 - 1254 - 1 - - - 1264 - regular - 1254 - 1242 - 1 - - - 1266 - regular - 1249 - 1239 - 1 - - - 1267 - regular - 1239 - 1255 - 1 - - - 1268 - regular - 1255 - 1237 - 1 - - - 1269 - regular - 1237 - 1250 - 1 - - - 1271 - regular - 1238 - 1252 - 1 - - - 1272 - regular - 1252 - 1243 - 1 - - - 1273 - regular - 1243 - 1251 - 1 - - - 1274 - regular - 1251 - 1240 - 1 - - - 1275 - regular - 1240 - 1246 - 1 - - - 1501 - regular - 1242 - 1249 - 1 - - - 1502 - regular - 1254 - 1282 - 1 - - - 1503 - regular - 1282 - 1286 - 1 - - - 1504 - regular - 1286 - 1281 - 1 - - - 1505 - regular - 1281 - 49 - 1 - - - 1511 - regular - 1508 - 1238 - 1 - - - 1515 - regular - 1508 - 1514 - 1 - - 1319 - 1643 - - - - 1516 - regular - 1514 - 1255 - 1 - - 432 - 1646 - - - - 1522 - regular - 1250 - 1521 - 1 - - 743 - 1489 - - - - 1523 - regular - 1521 - 1519 - 1 - - 988 - 1489 - - - - 1524 - regular - 1519 - 1520 - 1 - - 992 - 1367 - - - - 1525 - regular - 1520 - 1250 - 1 - - 744 - 1367 - - - - 1526 - regular - 1519 - 1507 - 1 - - 1100 - 1492 - - - - 1527 - regular - 1507 - 1508 - 1 - - 1327 - 1492 - - - - 1528 - regular - 1508 - 1513 - 1 - - 1329 - 1367 - - - - 1529 - regular - 1513 - 1519 - 1 - - 1102 - 1367 - - - - 1531 - regular - 1250 - 1530 - 1 - - 731 - 1293 - - - - 1532 - regular - 1530 - 1508 - 1 - - 1299 - 1295 - - - - 1533 - regular - 1508 - 1512 - 1 - - 1311 - 1561 - - - - 1534 - regular - 1512 - 1250 - 1 - - 729 - 1563 - - - - 1535 - regular - 1244 - 49 - 1 - - - 1536 - regular - 1247 - 1244 - 1 - - \ No newline at end of file diff --git a/src/main/resources/petriNets/all_data.xml b/src/main/resources/petriNets/all_data.xml index f65ed4ae659..e69de29bb2d 100644 --- a/src/main/resources/petriNets/all_data.xml +++ b/src/main/resources/petriNets/all_data.xml @@ -1,685 +0,0 @@ - - - data/all_data - All Data - ALL - All data test default case name - - true - - process_role - Process role - - - - number - Number - 10000 - - - number_currency - Number currency - 10000 - - - EUR - 2 - sk_SK - - - - - - text - Text - Lorem ipsum - - - password_data - Password from data - - password - - - - password_dataref - Password from dataRef - - - text_area - Text area - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vitae magna in libero semper - vulputate ut eu sapien. Phasellus vel. - - - textarea - red - 12 - - - - - enumeration - Enumeration - Alice - Bob - Carol - Bob - - - enumeration_autocomplete - Enumeration autocomplete - Alice - Bob - Carol - Bob - - autocomplete - - - - enumeration_list - Enumeration list - Alice - Bob - Carol - Bob - - list - - - - - enumeration_map - Enumeration Map - - - - - - bo - - - - multichoice - Multichoice - Alice - Bob - Carol - - Alice - Bob - - - - - multichoice_list - Multichoice list - Alice - Bob - Carol - Alice,Bob - - list - - - - - multichoice_map - Multichoice Map - - - - - - - al - ca - - - - - boolean - Boolean - True - - - - date - Date - 01.01.2019 - - - - taskRef - Task Ref - - 4 - - - - - file - File - - - textfield: f.text; - change textfield value { - "funguje to" - } - - - - - - fileList - File List - - - - user - User - - - - userList1 - UserList - - - - userList2 - UserList - - - - datetime - Datetime - 01.01.2019 20:00 - - - - button - Button - Push - - fab - - - - - taskref_test_field - Text datafield z iného transitionu - Field načítaný pomocou taskrefu - - - - 1 - 379 - 273 - - auto - - number - Number fields - false - 2 - - number - - editable - - - - number_currency - - editable - - - - - text - Text fields - false - - text - - editable - - - - text_area - - editable - - - - password_data - - editable - - - - password_dataref - - editable - - - password - - - - - enumeration - Enumeration fields - false - - enumeration - - editable - - - - enumeration_autocomplete - - editable - - - - enumeration_list - - editable - - - - enumeration_map - - editable - - - - - multichoice - Multichoice fields - false - - multichoice - - editable - - - - multichoice_list - - editable - - - - multichoice_map - - editable - - - - - boolean - Boolean fields - false - - boolean - - editable - - - - - date - Date fields - false - - date - - editable - - - - datetime - - editable - - - - - file - File fields - false - - file - - editable - - - - fileList - - editable - - - - - user - User fields - false - - user - - editable - - - - - button - Button fields - false - - button - - editable - - generatePdf("1","file") - - - - - - taskRef - Task refs - false - - taskRef - - editable - - - - - - 2 - 379 - 273 - - auto - - number - Number fields - false - - number - - visible - - - - number_currency - - visible - - - - - text - Text fields - false - - text - - visible - - - - text_area - - visible - - - - - enumeration - Enumeration fields - false - - enumeration - - visible - - - - enumeration_autocomplete - - visible - - - - enumeration_list - - visible - - - - enumeration_map - - visible - - - - - multichoice - Multichoice fields - false - - multichoice - - visible - - - - multichoice_list - - visible - - - - multichoice_map - - visible - - - - - boolean - Boolean fields - false - - boolean - - visible - - - - - date - Date fields - false - - date - - visible - - - - datetime - - visible - - - - - file - File fields - false - - file - - visible - - - - fileList - - visible - - - - - user - User fields - false - - user - - visible - - - - - button - Button fields - false - - button - - visible - - - - - - 3 - 379 - 273 - - auto - - stretch - Stretch - start - true - - text - - visible - - - - number - - editable - - - - enumeration - - editable - - - - - right - Alignment - Right - end - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - - - left - Alignment - Left - start - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - - - center - Alignment - Center - center - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - - - - 4 - 379 - 273 - - auto - - taskref - Task ref test group - - taskref_test_field - - editable - - - - - diff --git a/src/main/resources/petriNets/datamap.xml b/src/main/resources/petriNets/datamap.xml deleted file mode 100644 index b4f58f4bad6..00000000000 --- a/src/main/resources/petriNets/datamap.xml +++ /dev/null @@ -1,323 +0,0 @@ - - - data/taskref_demo2 - 1.0.0 - TRD - TaskRef demo 2 - home - true - false - - - - 1 - Block - - - - taskref_selector - Referenced tasks - Select referenced tasks - Fyzická osoba - Právnická osoba - SZČO - - - taskrefInput: f.taskref_selector, - taskref: f.taskref; - - change taskref value { - if (taskrefInput.value.defaultValue.contains("Fyzická osoba")) { - return [getTaskId("2")] - } else if (taskrefInput.value.defaultValue.contains("Právnická osoba")) { - return [getTaskId("3")] - } else { - return [getTaskId("4")] - } - } - - - - - taskref - set label - placeholder - description - value - - - - titule_pred - Titul pred - - - meno - Meno - - - priezvisko - Priezvisko - - - titule_za - Titul za - - - cislo_op - Číslo OP - - - narodnost - Národnosť - - - obchodne_meno - Obchodné meno - - - ico - IČO - - - - nested_taskref - Task ref with label - - - text1 - Field under task ref - This field is placed under the task ref field - - - - 1 - 340 - 260 - - 6 - - taskref_selector - - editable - - - 0 - 0 - 1 - 6 - - outline - - - - taskref - - editable - - - 0 - 1 - 1 - 6 - - outline - - - - text1 - - editable - - - 0 - 2 - 1 - 6 - - outline - - - - 1_assign - - - - taskref: f.nested_taskref; - change taskref value { - return [ - getTaskId("3"), - getTaskId("2") - ] - } - - - - - - - 2 - 500 - 180 - - 6 - - 1 - - true - - - - titule_pred - - editable - - - 0 - 0 - 1 - 1 - - outline - - - - meno - - editable - - - 1 - 0 - 1 - 2 - - outline - - - - priezvisko - - editable - - - 3 - 0 - 1 - 2 - - outline - - - - titule_za - - editable - - - 5 - 0 - 1 - 1 - - outline - - - - cislo_op - - editable - - - 0 - 1 - 1 - 3 - - outline - - - - narodnost - - editable - - - 3 - 1 - 1 - 3 - - outline - - - - - 3 - 500 - 260 - - 6 - - 1 - - true - - - - obchodne_meno - - editable - - - 0 - 0 - 1 - 3 - - outline - - - - ico - - editable - - - 3 - 0 - 1 - 3 - - outline - - - - - 4 - 500 - 340 - - 6 - - 1 - - true - - - - nested_taskref - - editable - - - 0 - 0 - 1 - 6 - - outline - - - - \ No newline at end of file diff --git a/src/main/resources/petriNets/engine-processes/all_data_transition_configuration.xml b/src/main/resources/petriNets/engine-processes/all_data_transition_configuration.xml index 961505d3fee..9ac80acfe06 100644 --- a/src/main/resources/petriNets/engine-processes/all_data_transition_configuration.xml +++ b/src/main/resources/petriNets/engine-processes/all_data_transition_configuration.xml @@ -1,22 +1,20 @@ - + + all_data_configuration - PAD + 1.0.0 All Data Configuration toc true true - false petriflow_all_data 0 0 - + All Data toc - - petriflow_all_data_datagroup - 4 - grid + + petriflow_all_data_layout - + - \ No newline at end of file + \ No newline at end of file diff --git a/src/main/resources/petriNets/engine-processes/dashboard.xml b/src/main/resources/petriNets/engine-processes/dashboard.xml index 6eea9d570be..aa89194a6b0 100644 --- a/src/main/resources/petriNets/engine-processes/dashboard.xml +++ b/src/main/resources/petriNets/engine-processes/dashboard.xml @@ -1,292 +1,289 @@ - - dashboard - DSH - Dashboard - dashboard - true - true - false - Dashboard - - name - Name - - - description - Description - - - cols - Columns - 2 - - - rows - Rows - 2 - - - dashboard - - <component> - <name>dashboard</name> - </component> - </data> - <i18n locale="sk"> - <i18nString name="task_t1_title">Konfigurácia</i18nString> - <i18nString name="data_name_title">Názov</i18nString> - <i18nString name="data_description_title">Popis</i18nString> - <i18nString name="data_cols_title">Počet stĺpcov</i18nString> - <i18nString name="data_rows_title">Počet riadkov</i18nString> - <i18nString name="data_group_share_title">Zdieľať so skupinami</i18nString> - <i18nString name="task_t2_event_t2_assign_title">Upraviť</i18nString> - <i18nString name="task_t2_event_t2_finish_title">Uložiť</i18nString> - <i18nString name="model_title">Nástenka</i18nString> - <i18nString name="model_default_case_name">Nástenka</i18nString> - <i18nString name="task_t2_title">Zobrazenie</i18nString> - </i18n> - <i18n locale="de"> - <i18nString name="task_t1_title">Aufbau</i18nString> - <i18nString name="data_name_title">Titel</i18nString> - <i18nString name="data_description_title">Beschreibung</i18nString> - <i18nString name="data_cols_title">Anzahl der Spalten</i18nString> - <i18nString name="data_rows_title">Anzahl der Reihen</i18nString> - <i18nString name="data_group_share_title">Mit Gruppen teilen</i18nString> - <i18nString name="task_t2_event_t2_assign_title">Anpassen</i18nString> - <i18nString name="task_t2_event_t2_finish_title">Speichern</i18nString> - <i18nString name="model_title">Dashboard</i18nString> - <i18nString name="model_default_case_name">Dashboard</i18nString> - <i18nString name="task_t2_title">Anzeige</i18nString> - </i18n> - <transition> - <id>t1</id> - <x>380</x> - <y>180</y> - <label name="task_t1_title">Configure</label> - <assignPolicy>auto</assignPolicy> - <dataGroup> - <id>t1_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>name</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>description</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>2</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - <component> - <name>textarea</name> - </component> - </dataRef> - <dataRef> - <id>cols</id> - <logic> - <behavior>editable</behavior> - <behavior>required</behavior> - </logic> - <layout> - <x>2</x> - <y>3</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>rows</id> - <logic> - <behavior>editable</behavior> - <behavior>required</behavior> - </logic> - <layout> - <x>0</x> - <y>3</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="assign"> - <id>t1_assign</id> - </event> - <event type="finish"> - <id>t1_finish</id> - <actions phase="post"> - <action id="1">name: f.name; - changeCaseProperty "title" about { name.value; }</action> - </actions> - </event> - <event type="cancel"> - <id>t1_cancel</id> - </event> - <event type="delegate"> - <id>t1_delegate</id> - </event> - </transition> - <transition> - <id>t2</id> - <x>620</x> - <y>180</y> - <label name="task_t2_title">Display</label> - <roleRef> - <id>default</id> - <logic> - <view>true</view> - <cancel>false</cancel> - <assign>true</assign> - <delegate>false</delegate> - <perform>true</perform> - </logic> - </roleRef> - <dataGroup> - <id>t2_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>dashboard</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>cols</id> - <logic> - <behavior>hidden</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>rows</id> - <logic> - <behavior>hidden</behavior> - </logic> - <layout> - <x>2</x> - <y>1</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="assign"> - <id>t2_assign</id> - <title name="task_t2_event_t2_assign_title">Edit - - - dashboard: f.dashboard; + + dashboard + DSH + Dashboard + dashboard + true + true + false + Dashboard + + name + Name + + + description + Description + + + cols + Columns + 2 + + + rows + Rows + 2 + + + dashboard + + <component> + <name>dashboard</name> + </component> + </data> + <i18n locale="sk"> + <i18nString name="task_t1_title">Konfigurácia</i18nString> + <i18nString name="data_name_title">Názov</i18nString> + <i18nString name="data_description_title">Popis</i18nString> + <i18nString name="data_cols_title">Počet stĺpcov</i18nString> + <i18nString name="data_rows_title">Počet riadkov</i18nString> + <i18nString name="data_group_share_title">Zdieľať so skupinami</i18nString> + <i18nString name="task_t2_event_t2_assign_title">Upraviť</i18nString> + <i18nString name="task_t2_event_t2_finish_title">Uložiť</i18nString> + <i18nString name="model_title">Nástenka</i18nString> + <i18nString name="model_default_case_name">Nástenka</i18nString> + <i18nString name="task_t2_title">Zobrazenie</i18nString> + </i18n> + <i18n locale="de"> + <i18nString name="task_t1_title">Aufbau</i18nString> + <i18nString name="data_name_title">Titel</i18nString> + <i18nString name="data_description_title">Beschreibung</i18nString> + <i18nString name="data_cols_title">Anzahl der Spalten</i18nString> + <i18nString name="data_rows_title">Anzahl der Reihen</i18nString> + <i18nString name="data_group_share_title">Mit Gruppen teilen</i18nString> + <i18nString name="task_t2_event_t2_assign_title">Anpassen</i18nString> + <i18nString name="task_t2_event_t2_finish_title">Speichern</i18nString> + <i18nString name="model_title">Dashboard</i18nString> + <i18nString name="model_default_case_name">Dashboard</i18nString> + <i18nString name="task_t2_title">Anzeige</i18nString> + </i18n> + <transition> + <id>t1</id> + <x>380</x> + <y>180</y> + <label name="task_t1_title">Configure</label> + <assignPolicy>auto</assignPolicy> + <grid> + <id>t1_grid</id> + <item> + <dataRef> + <id>name</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <grid-column>1 / span 2</grid-column> + </properties> + </item> + <item> + <dataRef> + <id>description</id> + <logic> + <behavior>editable</behavior> + </logic> + <component> + <name>textarea</name> + </component> + </dataRef> + <properties> + <grid-column>1 / span 2</grid-column> + </properties> + </item> + <item> + <dataRef> + <id>cols</id> + <logic> + <behavior>editable</behavior> + <behavior>required</behavior> + </logic> + </dataRef> + <properties> + <grid-column>1 / 2</grid-column> + </properties> + </item> + <item> + <dataRef> + <id>rows</id> + <logic> + <behavior>editable</behavior> + <behavior>required</behavior> + </logic> + </dataRef> + <properties> + <grid-column>2 / 3</grid-column> + </properties> + </item> + <properties> + <display>grid</display> + <grid-template-columns>repeat(2, 1fr)</grid-template-columns> + <justify-items>stretch</justify-items> + <align-items>stretch</align-items> + <justify-content>stretch</justify-content> + <align-content>stretch</align-content> + </properties> + </grid> + <event type="assign"> + <id>t1_assign</id> + </event> + <event type="finish"> + <id>t1_finish</id> + <actions phase="post"> + <action> + name: f.name; - for (dashboardTile in dashboard.value) { - try { - setData(dashboardTile, [ - "dashboard_filter_case_hidden": [ - "value": "false", - "type": "boolean" - ] - ]) - } catch (Exception ignored) { - log.error(dashboardTile+":"+(ignored as String)) - } - } - </action> - </actions> - </event> - <event type="finish"> - <id>t2_finish</id> - <title name="task_t2_event_t2_finish_title">Save - - - dashboard: f.dashboard; + changeCaseProperty "title" about { name.value } + + + + + t1_cancel + + + t1_delegate + + + + t2 + 620 + 180 + + + default + + true + false + true + false + true + + + + t2_grid + + + dashboard + + editable + + + + 1 / span 2 + + + + + cols + + hidden + + + + 1 / 2 + + + + + rows + + hidden + + + + 2 / 3 + + + + grid + repeat(2, 1fr) + stretch + stretch + stretch + stretch + + + + t2_assign + + + dashboard: f.dashboard; - for (dashboardTile in dashboard.value) { - try { - setData(dashboardTile, [ - "dashboard_filter_case_hidden": [ - "value": "true", - "type": "boolean" - ] - ]) - } catch (Exception ignored) { - log.error(dashboardTile+":"+(ignored as String)) - } - } - - - - - - p1 - 260 - 180 - 1 - false - - - p2 - 500 - 180 - 0 - false - - - a1 - regular - p1 - t1 - 1 - - - a2 - regular - t1 - p2 - 1 - - - a16 - read - p2 - t2 - 1 - + for (dashboardTile in dashboard.value) { + try { + setData(dashboardTile, [ + "dashboard_filter_case_hidden": [ + "value": "false", + "type" : "boolean" + ] + ]) + } catch (Exception ignored) { + log.error(dashboardTile + ":" + (ignored as String)) + } + } + + + Edit + + + t2_finish + + + dashboard: f.dashboard; + + for (dashboardTile in dashboard.value) { + try { + setData(dashboardTile, [ + "dashboard_filter_case_hidden": [ + "value": "true", + "type" : "boolean" + ] + ]) + } catch (Exception ignored) { + log.error(dashboardTile + ":" + (ignored as String)) + } + } + + + Save + + + + p1 + 260 + 180 + + + p2 + 500 + 180 + + + a1 + regular + p1 + t1 + 1 + + + a2 + regular + t1 + p2 + 1 + + + a16 + read + p2 + t2 + 1 + \ No newline at end of file diff --git a/src/main/resources/petriNets/engine-processes/export_filters.xml b/src/main/resources/petriNets/engine-processes/export_filters.xml index e057c9cb800..a4bd80535a0 100644 --- a/src/main/resources/petriNets/engine-processes/export_filters.xml +++ b/src/main/resources/petriNets/engine-processes/export_filters.xml @@ -1,12 +1,11 @@ - + export_filters - FTE - Export of filters + 1.0.0 + Export of filters file_download true - false - Export of filters + Export of filters @@ -15,131 +14,131 @@ exportable_filters - Exportable filters - List of all exportable filters - Select one or more filters to export - - exportable_filters: f.exportable_filters; + Exportable filters + List of all exportable filters + Select one or more filters to export + + exportable_filters_get + + + exportable_filters: f.exportable_filters; - change exportable_filters options { - return findAllFilters() - .collectEntries({filterCase -> [filterCase.stringId, filterCase.title]}) - } - + change exportable_filters options { + return findAllFilters() + .collectEntries({filterCase -> [filterCase.stringId, filterCase.title]}) + } + + + export_btn - Export filters - Export selected filters into xml file - - exportable_filters: f.exportable_filters, - export_file: f.export_file, - trans: t.exportFilter; + Export filters + Export selected filters into xml file + + export_btn_set + + + exportable_filters: f.exportable_filters, + export_file: f.export_file, + trans: t.exportFilter; - change export_file value { exportFilters(exportable_filters.value) } - change exportable_filters value { [] } - make export_file, visible on trans when {exportable_filters.value.length != 0} - make export_file, hidden on trans when {exportable_filters.value.length == 0} - + change export_file value { exportFilters(exportable_filters.value) } + change exportable_filters value { [] } + make export_file, visible on trans when {exportable_filters.value.length != 0} + make export_file, hidden on trans when {exportable_filters.value.length == 0} + + + - raised + raised export_file - Exported filters - File with exported filters - Download file with exported filters in xml format + Exported filters + File with exported filters + Download file with exported filters in xml format - Export filtrov - Exportovateľné filtre - Zoznam všetkých exportovateľných filtrov - Vyberte jeden alebo viac filtrov na export - Exportovať filtre - Export vybraných filtrov do súboru xml - Exportované filtre - Súbor s exportovanými filtrami - Stiahnutie súboru s exportovanými filtrami vo formáte xml + Export filtrov + Exportovateľné filtre + Zoznam všetkých exportovateľných filtrov + Vyberte jeden alebo viac filtrov na export + Exportovať filtre + Export vybraných filtrov do súboru xml + Exportované filtre + Súbor s exportovanými filtrami + Stiahnutie súboru s exportovanými filtrami vo formáte xml - Exportieren von Filtern - Exportierbare Filter - Liste aller exportierbaren Filter - Wählen Sie einen oder mehrere Filter für den Export - Filter exportieren - Ausgewählte Filter in xml-Datei exportieren - Exportierte Filter - Datei mit exportierten Filtern - Datei mit exportierten Filtern im xml-Format herunterladen + Exportieren von Filtern + Exportierbare Filter + Liste aller exportierbaren Filter + Wählen Sie einen oder mehrere Filter für den Export + Filter exportieren + Ausgewählte Filter in xml-Datei exportieren + Exportierte Filter + Datei mit exportierten Filtern + Datei mit exportierten Filtern im xml-Format herunterladen exportFilter 200 100 - - 0 - + Export filters auto - - - DataGroup_0 - grid - - exportable_filters - - editable - - - 0 - 0 - 1 - 2 - 0 - - outline - - - - export_btn - - editable - - - 2 - 0 - 1 - 2 - 0 - - outline - - - - export_file - - hidden - - - 0 - 1 - 1 - 2 - 0 - - outline - - - + + exportFilter_grid + + + exportable_filters + + editable + + + + 1 / 2 + + + + + export_btn + + editable + + + + 2 / 3 + + + + + export_file + + hidden + + + + 1 / 2 + + + + grid + repeat(2, 1fr) + stretch + stretch + stretch + stretch + + + exportFilter_assign - export_file: f.export_file, - trans: t.exportFilter; - - make export_file, hidden on trans when {true} + make export_file, hidden on exportFilter when {true} @@ -149,9 +148,7 @@ p1 100 100 - 1 - false @@ -168,4 +165,4 @@ p1 1 - + diff --git a/src/main/resources/petriNets/engine-processes/filter.xml b/src/main/resources/petriNets/engine-processes/filter.xml index c81771b4f18..68c32ee2277 100644 --- a/src/main/resources/petriNets/engine-processes/filter.xml +++ b/src/main/resources/petriNets/engine-processes/filter.xml @@ -1,1094 +1,471 @@ - - + filter - FTR - Filter + 1.0.0 + Filter filter_alt true - false - New filter - + false + + FTR + + New filter + - create + case_create - - caseId: f.filter_case_id; - - change caseId value {return useCase.stringId}; - + + + - - system System - - - - { - com.netgrif.application.engine.petrinet.domain.dataset.TaskField myFullFilter - -> - change myFullFilter value {return [findTask({it.caseId.eq(useCase.stringId).and(it.transitionId.eq("view_filter"))}).stringId]} - } + + change myFullFilter value {return [findTask({it.caseId.eq(useCase.stringId).and(it.transitionId.eq("view_filter"))}).stringId]} + } + ]]> - + + allowed_nets + Allowed nets + + + and_me + + <placeholder id="and">AND</placeholder> + </data> + <data type="button"> + <id>and_view</id> + <title/> + <placeholder id="and">AND</placeholder> + </data> + <data type="i18n"> + <id>divider_1</id> + <title/> + <component> + <id>divider</id> + </component> + </data> <data type="filter" immediate="true"> <id>filter</id> - <title name="filter_field">Filter + Filter + + + filter_case_id + </data> <data type="enumeration_map" immediate="true"> <id>filter_type</id> - <title name="filter_type">Filter type + Filter type - - + + - - visibility - Filter visibility + + i18n_filter_name + + </data> + <data type="number"> + <id>is_imported</id> + <title>imported + 0 + + is_imported_set + + + + + + + + + is_not_imported + not imported + 1 + + + menu_identifier + + </data> + <data type="text"> + <id>missing_allowed_nets</id> + <title id="missing_allowed_nets">Missing processes + List of missing processes for current filter + + htmltextarea + + + + missing_nets_translation + <options> - <option key="public" name="filter_visibility_public">Public</option> - <option key="private" name="filter_visibility_private">Private</option> + <option key="sk">Zoznam chýbajúcich procesov pre aktuálny filter:</option> + <option key="en">List of missing processes for current filter:</option> + <option key="de">Liste der fehlenden Prozesse für den aktuellen Filter:</option> </options> - <init>public</init> + </data> + <data type="taskRef"> + <id>my_full_filter</id> + <title/> + </data> + <data type="text"> + <id>new_title</id> + <title id="filter_name">Filter name origin_view_id - Origin ViewId + Origin ViewId - set + origin_view_id_set - - origin_view_id: f.origin_view_id, - and_view: f.and_view, - trimmed_origin_view_id: f.trimmed_origin_view_id, - t1: t.view_filter, - t2: t.view_as_ancestor; - + + + ]]> + parent_filter_id - parent filter ID + parent filter ID - set + parent_filter_id_set - - parent_filter_id: f.parent_filter_id, - ancestor_task_ref: f.taskref_and_parent; - + + + change taskref_and_parent value {[ancestor_view_filter.stringId]} + ]]> + - - new_title - Filter name - - - i18n_filter_name - - - - filter_case_id - - - - menu_identifier - - - - and_me - AND - - - and_view - AND - taskref_and_parent - + </data> <data type="text"> <id>trimmed_origin_view_id</id> - <title name="filter_from_view_id">Filter from view with ID - - - is_imported - imported - 0 - - isNotImported: f.is_not_imported; - - change isNotImported value { return 0 } - - - - is_not_imported - not imported - 1 + Filter from view with ID - - missing_allowed_nets - Missing processes - List of missing processes for current filter - - htmltextarea - - - - missing_nets_translation - + + visibility + Filter visibility - - - + + + public - - my_full_filter - - - - allowed_nets - Allowed nets - - - Filter - Nový Filter - Filter - Druh filtra - Filter prípadov - Filter úloh - Viditeľnosť filtra - Verejný - Súkromný - ViewId pôvodu - Názov filtra - Vytvoriť nový filter - Podrobnosti - Uložiť - A SÚČASNE - Filter z obrazovky s ID - Názov prípadu - Importovať filter - Chýbajúce procesy - Zoznam chýbajúcich procesov pre aktuálny filter - ID rodičovského filtra - Povolené siete + Filter + Nový Filter + Filter + Druh filtra + Filter prípadov + Filter úloh + Viditeľnosť filtra + Verejný + Súkromný + ViewId pôvodu + Názov filtra + Vytvoriť nový filter + Podrobnosti + Uložiť + A SÚČASNE + Filter z obrazovky s ID + Názov prípadu + Importovať filter + Chýbajúce procesy + Zoznam chýbajúcich procesov pre aktuálny filter + ID rodičovského filtra + Povolené siete - Filter - Neuer Filter - Filter - Filtertyp - Fallfilter - Aufgabenfilter - Filter Sichtbarkeit - Öffentlich - Persönlich - Herkunft ViewId - Filtername - Neuer Filter erstellen - Details - Speichern - UND - Filter von der Ansicht mit der ID - Fallname - Importfilter - Fehlende Prozesse - Liste der fehlenden Prozesse für den aktuellen Filter - Elternfilter-ID - Erlaubte Netze + Filter + Neuer Filter + Filter + Filtertyp + Fallfilter + Aufgabenfilter + Filter Sichtbarkeit + Öffentlich + Persönlich + Herkunft ViewId + Filtername + Neuer Filter erstellen + Details + Speichern + UND + Filter von der Ansicht mit der ID + Fallname + Importfilter + Fehlende Prozesse + Liste der fehlenden Prozesse für den aktuellen Filter + Elternfilter-ID + Erlaubte Netze - - newFilter - 620 - 260 - - - 0 - - auto - - myFilter - grid - - my_full_filter - - visible - - - 0 - 0 - 1 - 4 - 0 - - - - - DataGroup_0 - grid - - visibility - - editable - required - - - 0 - 1 - 1 - 4 - 0 - - outline - - - - new_title - - editable - required - - userTitle: f.new_title, - i18nName: f.i18n_filter_name; - - change i18nName value { new com.netgrif.application.engine.petrinet.domain.I18nString(userTitle.rawValue) } - - - - 0 - 2 - 1 - 4 - 0 - - outline - - - - allowed_nets - - editable - - - 0 - 3 - 1 - 4 - 0 - - outline - - - + auto_create + 500 + 180 + Automated new filter - - Save + auto_create_finish - - name: f.new_title; - useCase.setTitle(name.rawValue) - workflowService.save(useCase) - + + + - - t2 - 740 - 380 - - 0 - - - - DataGroup_0 - grid - - filter_type - - visible - - - 0 - 0 - 1 - 1 - 0 - - outline - - - - visibility - - visible - - - 1 - 0 - 1 - 1 - 0 - - outline - - - - - myFilter - grid - - my_full_filter - - visible - - - 0 - 0 - 1 - 4 - 0 - - - - frontend_create 380 260 - - - 0 - - - DataGroup_0 - grid - - filter - - editable - - - 0 - 0 - 1 - 4 - 0 - - outline - - - - filter_type - - editable - - - 0 - 1 - 1 - 4 - 0 - - outline - - - - origin_view_id - - editable - - - 0 - 2 - 1 - 4 - 0 - - outline - - - - parent_filter_id - - editable - - - 0 - 3 - 1 - 4 - 0 - - outline - - - - allowed_nets - - editable - - - 0 - 4 - 1 - 4 - 0 - - outline - - - + Set filter metadata - finish + frontend_create_finish - - taskRef: f.my_full_filter; - - initializeMyFullFilterTaskRef(taskRef) - + + + - auto_create - 500 + import_filter + 740 180 - - - 0 - - - DataGroup_0 - grid - - filter - - editable - - - 0 - 0 - 1 - 1 - 0 - - outline - - - - filter_type - - editable - - - 1 - 0 - 1 - 1 - 0 - - outline - - - - visibility - - editable - - - 2 - 0 - 1 - 1 - 0 - - outline - - - - origin_view_id - - editable - - - 3 - 0 - 1 - 1 - 0 - - outline - - - - parent_filter_id - - editable - - - 0 - 1 - 1 - 1 - 0 - - outline - - - + Import filter - finish + import_filter_finish - - taskRef: f.my_full_filter; - - initializeMyFullFilterTaskRef(taskRef) - + + + - view_filter - 550 - 420 - - - 0 - - - system - - true - - - - DataGroup_0 - grid - - filter - - visible - - - 0 - 0 - 1 - 4 - 0 - - outline - - - - filter_case_id - - hidden - - - 0 - 1 - 1 - 4 - 0 - - outline - - - - origin_view_id - - forbidden - - - 0 - 2 - 1 - 4 - 0 - - outline - - - - taskref_and_parent - - visible - - - 0 - 3 - 1 - 4 - 0 - - outline - - - - new_title - - hidden - - name: f.new_title, - i18nName: f.i18n_filter_name; - - change i18nName value { new com.netgrif.application.engine.petrinet.domain.I18nString(name.rawValue) } - - - - 0 - 4 - 1 - 4 - 0 - - outline - - - - - DataGroup_1 - grid - - and_view - - forbidden - - - 0 - 0 - 1 - 1 - 0 - - outline - - - - trimmed_origin_view_id - - forbidden - - - 1 - 0 - 1 - 3 - 0 - - outline - - - + newFilter + 620 + 260 + Create new filter + auto + + newFilter_finish + + + + + + Save + + + + t2 + 740 + 380 + Details view_as_ancestor 451 418 - - - 0 - + <roleRef> <id>system</id> - <logic> + <permission> <view>true</view> - </logic> + </permission> </roleRef> - <dataGroup> - <id>DataGroup_0</id> - <layout>grid</layout> - <dataRef> - <id>and_me</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>1</cols> - <offset>0</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>filter</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>1</x> - <y>0</y> - <rows>1</rows> - <cols>3</cols> - <offset>0</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>taskref_and_parent</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>0</x> - <y>3</y> - <rows>1</rows> - <cols>4</cols> - <offset>0</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <dataGroup> - <id>DataGroup_1</id> - <layout>grid</layout> - <dataRef> - <id>and_view</id> - <logic> - <behavior>forbidden</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>1</cols> - <offset>0</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>trimmed_origin_view_id</id> - <logic> - <behavior>forbidden</behavior> - </logic> - <layout> - <x>1</x> - <y>0</y> - <rows>1</rows> - <cols>3</cols> - <offset>0</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>origin_view_id</id> - <logic> - <behavior>forbidden</behavior> - </logic> - <layout> - <x>0</x> - <y>3</y> - <rows>1</rows> - <cols>3</cols> - <offset>0</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> </transition> <transition> - <id>import_filter</id> - <x>740</x> - <y>180</y> - <label name="import_filter">Import filter</label> - <layout> - <offset>0</offset> - </layout> - <dataGroup> - <id>DataGroup_0</id> - <layout>grid</layout> - <title> - - new_title - - editable - - name: f.new_title; - - change name value { useCase.getTitle() } - - - name: f.new_title, - i18nName: f.i18n_filter_name; - - change i18nName value { new com.netgrif.application.engine.petrinet.domain.I18nString(name.rawValue) } - - - - 0 - 0 - 1 - 1 - 0 - - outline - - - - filter_type - - visible - - - 1 - 0 - 1 - 1 - 0 - - outline - - - - visibility - - editable - - - 2 - 0 - 1 - 1 - 0 - - outline - - - - missing_allowed_nets - - hidden - - - 0 - 2 - 1 - 2 - 0 - - outline - - - - - DataGroup_1 - grid - - my_full_filter - - visible - - - 0 - 0 - 1 - 4 - 0 - - outline - - - - - - - - name: f.new_title; - changeCaseProperty "title" about { name.rawValue } - - - - + view_filter + 550 + 420 + View filter + + system + + true + + - p1 260 260 - 1 - false p2 740 260 - 0 - false p3 540 260 - 0 - false p4 660 140 - 0 - false p5 500 340 - 0 - false - - a3 + a12 regular - p1 - frontend_create + import_filter + p2 1 - a4 + a13 regular - frontend_create - p3 - 1 + auto_create + p4 + + + - a5 + a14 regular - p3 - newFilter + p4 + import_filter 1 - a6 + a15 regular - newFilter - p2 + frontend_create + p5 1 - a7 + a18 read - p2 - t2 + p5 + view_as_ancestor 1 - a8 - regular - p1 - auto_create + a19 + read + p5 + view_filter 1 - a9 + a20 regular auto_create - p2 + p5 1 - is_not_imported - a12 + a3 regular - import_filter - p2 + p1 + frontend_create 1 - a13 + a4 regular - auto_create - p4 - 0 - is_imported + frontend_create + p3 + 1 - a14 + a5 regular - p4 - import_filter + p3 + newFilter 1 - a15 + a6 regular - frontend_create - p5 + newFilter + p2 1 - a18 + a7 read - p5 - view_as_ancestor + p2 + t2 1 - a19 - read - p5 - view_filter + a8 + regular + p1 + auto_create 1 - a20 + a9 regular auto_create - p5 - 1 + p2 + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/main/resources/petriNets/engine-processes/group.xml b/src/main/resources/petriNets/engine-processes/group.xml new file mode 100644 index 00000000000..b1848ba6120 --- /dev/null +++ b/src/main/resources/petriNets/engine-processes/group.xml @@ -0,0 +1,147 @@ + + group + 1.0.0 + Group + groups + false + false + Group + + admin + + true + true + true + + + + + group_removal + + + def actors = allActorService.findAll() + actors.each { actor -> + if (actor.stringId == useCase.stringId) { + return + } + actor = userService.removeGroup(actor, useCase.stringId) + if (actor.case.processIdentifier != com.netgrif.application.engine.authorization.domain.constants.GroupConstants.PROCESS_IDENTIFIER) { + return + } + def typedActor = (com.netgrif.application.engine.authorization.domain.Group) actor + if (typedActor.parentGroupId != useCase.stringId) { + return + } + groupService.update(actor, com.netgrif.application.engine.authorization.domain.params.GroupParams.with() + .parentGroupId(com.netgrif.application.engine.petrinet.domain.dataset.CaseField.withValue([])) + .build()) + } + + + + + + admin + Admin + + + name + Email + + + groupIds + Groups + + groupIds_set + + + if (groupIds.value == null) { + return + } + if (groupIds.rawValue.contains(useCase.stringId)) { + throw new IllegalArgumentException("Cannot add self as member of the group.") + } + + + + + group + + + + parentGroupId + Parent group id + + parentGroupId_set + + + if (parentGroupId.value == null) { + return + } + if (parentGroupId.rawValue.size() > 1) { + throw new IllegalArgumentException("Cannot have multiple references to parent group") + } + if (parentGroupId.rawValue[0] == useCase.stringId) { + throw new IllegalArgumentException("Cannot use self reference as parent group") + } + + + + + group + + + + + t1 + 368 + 208 + Data + + admin + + true + + + + t1_flex + + + name + + editable + + + + + + parentGroupId + + visible + + + + + + groupIds + + visible + + + + + + + p1 + 368 + 304 + 1 + + + a1 + read + p1 + t1 + 1 + + \ No newline at end of file diff --git a/src/main/resources/petriNets/engine-processes/identity.xml b/src/main/resources/petriNets/engine-processes/identity.xml new file mode 100644 index 00000000000..d2708ef7710 --- /dev/null +++ b/src/main/resources/petriNets/engine-processes/identity.xml @@ -0,0 +1,161 @@ + + identity + 1.0.0 + Identity + person + false + false + Identity + + admin + + true + true + true + + + + admin + Admin + + + username + Username + + + firstname + First name + + + lastname + Last name + + + password + Password + + + active_actor_id + + <allowedNets> + <allowedNet>user</allowedNet> + </allowedNets> + </data> + <data type="caseRef"> + <id>main_actor_id</id> + <title/> + <allowedNets> + <allowedNet>user</allowedNet> + </allowedNets> + </data> + <data type="caseRef"> + <id>additional_actor_ids</id> + <title/> + <allowedNets> + <allowedNet>user</allowedNet> + </allowedNets> + </data> + <data type="enumeration_map" immediate="true"> + <id>state</id> + <title>State + + + + + + + + + registration_token + Registration token + + + expiration_date + Expiration date + + + + t1 + 368 + 208 + Data + + admin + + true + + + + t1_flex + + + username + + editable + + + + + + firstname + + editable + + + + + + lastname + + editable + + + + + + main_actor_id + + visible + + + + + + additional_actor_ids + + visible + + + + + + state + + editable + + + + + + expiration_date + + editable + + + + + + + p1 + 368 + 304 + 1 + + + a1 + read + p1 + t1 + 1 + + \ No newline at end of file diff --git a/src/main/resources/petriNets/engine-processes/impersonation_config.xml b/src/main/resources/petriNets/engine-processes/impersonation_config.xml deleted file mode 100644 index 87f07da270f..00000000000 --- a/src/main/resources/petriNets/engine-processes/impersonation_config.xml +++ /dev/null @@ -1,826 +0,0 @@ - - impersonation_config - 1.0.0 - IPC - Impersonators configuration - supervisor_account - false - false - false - Impersonators configuration - - - { String ownerId -> - def user = userService.loggedOrSystem - def adminProcessRole = useCase.petriNet.roles.values().find { it.importId == "admin_imp" } - if (user.stringId != ownerId && !user.getProcessRoles().any { it.stringId == adminProcessRole.stringId }) { - throw new IllegalArgumentException("User is not allowed to manipulate other users' impersonation configurations!") - } - } - - - - Konfigurácia zastupiteľov - Používateľ - E-mail zastúpeného - Nastavení zastupitelia - Platnosť od - Platnosť do - Aktívna konfigurácia - Používateľ na zastúpenie - Vymazať označených - Pridať vybraného - Zastúpené autority - Zastúpené procesné roly - Výber zastupiteľov - Deaktivovať - Znovu aktivovať - Publikovať - - - - Vertreter Konfiguration - Benutzer - E-Mail-Adresse des Vertreters - Konfigurierte Vertreter - Gültig ab - Gültig bis - Aktive Konfiguration - Benutzer zu vertreten - Ausgewählte löschen - Ausgewählte hinzufügen - Vertretene Berechtigungen - Vertretene Rollen - Vertreter auswählen - Deaktivieren - Reaktivieren - Veröffentlichen - - - admin_imp - - true - true - true - - - - user_imp - - true - true - - - - default - - true - - - - config_owner - - true - true - - - - - create - - - - impersonated_email: f.impersonated_email, - impersonated: f.impersonated, - config_owner: f.config_owner; - - IUser user = userService.loggedOrSystem - UserFieldValue impersonatedValue = new UserFieldValue(user) - change impersonated value { impersonatedValue } - change impersonated_email value { user.email } - change config_owner value { new UserListFieldValue([impersonatedValue]) } - - - - - user_select_caseId: f.user_select_caseId, - user_select_taskRef: f.user_select_taskRef; - - def userSelectCase = createCase("impersonation_users_select") - def taskId = userSelectCase.getTaskStringId("select_user") - change user_select_taskRef value { [taskId] } - change user_select_caseId value { userSelectCase.stringId } - setData(taskId, new DataSet([ - "parentId": new TextField(rawValue: useCase.stringId) - ])) - - - - - - - admin_imp - Admin - - - user_imp - User - - - impersonated_email - Impersonated email - - impersonated_email_set - - - - impersonators - Configured impersonators - - list - - - - - - - impersonated: f.impersonated; - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - - - - - - - config_owner - - </data> - <data type="dateTime" immediate="true"> - <id>valid_from</id> - <title name="valid_from">Valid from - - - - - impersonated: f.impersonated; - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - - - - - - valid_to - Valid until - - - - - impersonated: f.impersonated; - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - - - - - - is_active - Is active - - - - - impersonated: f.impersonated; - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - - - - - - impersonated - User to impersonate - - impersonated_set - - - impersonated: f.impersonated; - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - - - - - impersonated_email: f.impersonated_email, - impersonated: f.impersonated; - - change impersonated_email value { impersonated.rawValue.email } - - - - - - - remove_impersonator - - <placeholder name="remove_impersonator">Remove selected</placeholder> - <event type="set"> - <id>remove_impersonator_set</id> - <actions phase="pre"> - <action> - impersonated: f.impersonated; - - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - </action> - <action id="action_2"> - impersonators: f.impersonators; - - if (impersonators.value != null && impersonators.options != null) { - def options = impersonators.options - def values = impersonators.value - values.each { it -> options.remove(it) } - change impersonators value { null } - change impersonators options { options } - } - </action> - </actions> - </event> - </data> - <data type="button"> - <id>add_selected</id> - <title/> - <placeholder name="add_selected">Add selected</placeholder> - <event type="set"> - <id>add_selected_set</id> - <actions phase="pre"> - <action> - impersonated: f.impersonated; - - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - </action> - <action id="10"> - user_select_caseId: f.user_select_caseId, - user_select_taskRef: f.user_select_taskRef, - impersonators: f.impersonators; - - def userSelectCase = workflowService.findOne(user_select_caseId.value) - def selectedUserField = userSelectCase.dataSet["select_impersonator"] - - if (!selectedUserField.value || !selectedUserField.options[selectedUserField.value]) { - return - } - - def options = impersonators.options != null ? impersonators.options : [:] as java.util.Map - options.put(selectedUserField.value, selectedUserField.options[selectedUserField.value]) - options = options.sort { it.value } - change impersonators options { options } - change impersonators value { options.keySet() } - - setData((user_select_taskRef.value as List)[0], [ - "select_impersonator": ["type": "enumeration_map", "value": ""] - ]) - </action> - </actions> - </event> - </data> - <data type="multichoice_map" immediate="true"> - <id>impersonated_authorities</id> - <title name="impersonated_authorities">Impersonated authorities - - - - - impersonated: f.impersonated; - - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - - - - - impersonated_authorities_get - - - - impersonated: f.impersonated, - impersonated_authorities: f.impersonated_authorities; - - def impersonatedUser = userService.findById(impersonated.rawValue.id, false) - change impersonated_authorities options { - impersonatedUser.authorities.collectEntries { [(it.stringId): (it.name)] } - } - - - - - - impersonated_roles - Impersonated roles - - - - - impersonated: f.impersonated; - - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - - - - - impersonated_roles - - - - impersonated: f.impersonated, - impersonated_roles: f.impersonated_roles; - - def impersonatedUser = userService.findById(impersonated.rawValue.id, false) - change impersonated_roles options { - return impersonatedUser.processRoles.findAll { it.netId }.sort { it.netId }.collectEntries { - def net = petriNetService.get(new org.bson.types.ObjectId(it.netId)) - return [(it.stringId): ("$it.name ($net.title $net.identifier-$net.version)" as String)] - } - } - - - - - - user_select_taskRef - - </data> - <data type="text"> - <id>user_select_caseId</id> - <title/> - </data> - <transition> - <id>t2</id> - <x>500</x> - <y>180</y> - <label name="configure_impersonators">Configure impersonators</label> - <assignPolicy>auto</assignPolicy> - <roleRef> - <id>admin_imp</id> - <logic> - <view>true</view> - <cancel>true</cancel> - <assign>true</assign> - <delegate>true</delegate> - <perform>true</perform> - </logic> - </roleRef> - <userRef> - <id>config_owner</id> - <logic> - <view>true</view> - <cancel>true</cancel> - <assign>true</assign> - <delegate>true</delegate> - <perform>true</perform> - </logic> - </userRef> - <dataGroup> - <id>t2_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>impersonators</id> - <logic> - <behavior>editable</behavior> - - </logic> - <layout> - <x>0</x> - <y>2</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>valid_from</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>4</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>valid_to</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>4</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>remove_impersonator</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>2</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - <component> - <name>stroked</name> - </component> - </dataRef> - <dataRef> - <id>add_selected</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>1</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - <component> - <name>stroked</name> - </component> - </dataRef> - <dataRef> - <id>impersonated_authorities</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>3</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - - <component> - <name>list</name> - </component> - </dataRef> - <dataRef> - <id>impersonated_roles</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>3</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - <component> - <name>list</name> - </component> - </dataRef> - <dataRef> - <id>user_select_taskRef</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="finish"> - <id>finish</id> - <title name="publish">Publish - - - - impersonated: f.impersonated; - - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - - - - - impersonated: f.impersonated; - - impersonationService.removeImpersonatorByImpersonated(impersonated.rawValue.id) - - - is_active: f.is_active; - - change is_active value { true } - - - - - - t3 - 660 - 300 - - auto - - - admin_imp - - true - true - true - true - true - - - - config_owner - - true - true - true - true - true - - - - - assign - - - impersonated: f.impersonated; - - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - - - - - finish - - - impersonated: f.impersonated; - - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - - - - - is_active: f.is_active; - - change is_active value { false } - - - - - - t4 - 820 - 180 - - auto - - - admin_imp - - true - true - true - true - true - - - - config_owner - - true - true - true - true - true - - - - - t4_0 - 4 - grid - - impersonators - - visible - - - 0 - 0 - 1 - 4 - - outline - - - - impersonated_authorities - - visible - - - 2 - 1 - 1 - 2 - - outline - - - - impersonated_roles - - visible - - - 0 - 1 - 1 - 2 - - outline - - - - valid_from - - visible - - - 0 - 2 - 1 - 2 - - outline - - - - valid_to - - visible - - - 2 - 2 - 1 - 2 - - outline - - - - - - assign - - - impersonated: f.impersonated; - - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - - - - - finish - - - impersonated: f.impersonated; - - if (impersonated.rawValue) { - validateUser(impersonated.rawValue.id) - } - - - - - is_active: f.is_active; - - change is_active value { true } - - - - - - p2 - 660 - 180 - 1 - false - - - p3 - 820 - 300 - 0 - false - - - p4 - 660 - 100 - 0 - false - - - a2 - regular - t2 - p2 - 1 - - - a3 - regular - p2 - t3 - 1 - - - a4 - regular - t3 - p3 - 1 - - - a5 - regular - p3 - t4 - 1 - - - a6 - regular - t4 - p2 - 1 - - - a14 - regular - p2 - t2 - 1 - - - a15 - regular - t2 - p4 - 1 - - - a16 - read - p4 - t3 - 1 - - \ No newline at end of file diff --git a/src/main/resources/petriNets/engine-processes/impersonation_users_select.xml b/src/main/resources/petriNets/engine-processes/impersonation_users_select.xml deleted file mode 100644 index aa0d581e141..00000000000 --- a/src/main/resources/petriNets/engine-processes/impersonation_users_select.xml +++ /dev/null @@ -1,96 +0,0 @@ - - impersonation_users_select - 1.0.0 - IPU - Impersonators configuration - user select - home - false - false - false - - - - Výber zastupiteľa - Vyhľadajte podľa mena alebo emailovej adresy - Konfigurácia zastupiteľov - user select - - - Vertreter auswählen - Suche nach Name oder E-Mail-Adresse - Vertreter Konfiguration - user select - - - - parentId - - </data> - <data type="enumeration_map"> - <id>select_impersonator</id> - <title name="select_impersonator">Select impersonator - - autocomplete_dynamic - - Search by name or email address - - select_impersonator_set - - - - select_impersonator: f.select_impersonator; - - if (!select_impersonator.value) { - change select_impersonator options { [:] } - - } else if (!select_impersonator.options.containsKey(select_impersonator.value)) { - def selectableUsers = userService.searchAllCoMembers( - select_impersonator.value, - userService.loggedUser.transformToLoggedUser(), - false, - new com.netgrif.application.engine.utils.FullPageRequest()).content - change select_impersonator options { - [*selectableUsers].sort { it?.surname }.collectEntries { [(it.id): ("${it?.fullName} ($it.email)" as String)] } - } - } - - - - - - - select_user - 500 - 180 - - - select_user_0 - 4 - grid - - select_impersonator - - editable - - - 0 - 0 - 1 - 4 - - outline - - - - - t2_assign - - - t2_finish - - - t2_cancel - - - t2_delegate - - - \ No newline at end of file diff --git a/src/main/resources/petriNets/engine-processes/import_filters.xml b/src/main/resources/petriNets/engine-processes/import_filters.xml index ba4f173f298..2fb945829ed 100644 --- a/src/main/resources/petriNets/engine-processes/import_filters.xml +++ b/src/main/resources/petriNets/engine-processes/import_filters.xml @@ -1,12 +1,11 @@ - + import_filters - FTI - Import of filters + 1.0.0 + Import of filters file_upload true - false - Import of filters + Import of filters @@ -15,140 +14,164 @@ upload_file - Upload filter file - Insert file containing filters - Insert xml file that contains filters - - importedFilters: f.imported_filters; + Upload filter file + Insert file containing filters + Insert xml file that contains filters + + upload_file_set + + + importedFilters: f.imported_filters; - taskService.findAllById(importedFilters.value).forEach({filterTask -> - workflowService.deleteCase(filterTask.caseId) - }) - change importedFilters value { return [] } - + taskService.findAllById(importedFilters.value).forEach({filterTask -> + deleteCase(filterTask.caseId) + }) + change importedFilters value { return [] } + + + import_file - Import filters - Import filters from uploaded xml file + Import filters + Import filters from uploaded xml file - raised + raised imported_filters - - - importedFilters: f.imported_filters; + + <event type="set"> + <id>imported_filters_set</id> + <actions phase="post"> + <action> + importedFilters: f.imported_filters; - filterImportExportService.changeFilterField(importedFilters.value) - </action> + filterImportExportService.changeFilterField(importedFilters.value) + </action> + </actions> + </event> </data> + + + <data type="i18n"> + <id>divider_1</id> + <title/> + <component> + <id>divider</id> + </component> + </data> + <!-- I18NS --> <i18n locale="sk"> - <i18nString name="import_filters">Import filtrov</i18nString> - <i18nString name="upload_file">Nahratie súboru s filtrami</i18nString> - <i18nString name="upload_file_placeholder">Vložete súbor obsahujúci filtre</i18nString> - <i18nString name="upload_file_desc">Vložte xml súbor, ktorý obsahuje filtre</i18nString> - <i18nString name="import_file_placeholder">Importovať filtre</i18nString> - <i18nString name="import_file_desc">Importovať filtre z nahraného xml súboru</i18nString> + <i18nString id="import_filters">Import filtrov</i18nString> + <i18nString id="upload_file">Nahratie súboru s filtrami</i18nString> + <i18nString id="upload_file_placeholder">Vložete súbor obsahujúci filtre</i18nString> + <i18nString id="upload_file_desc">Vložte xml súbor, ktorý obsahuje filtre</i18nString> + <i18nString id="import_file_placeholder">Importovať filtre</i18nString> + <i18nString id="import_file_desc">Importovať filtre z nahraného xml súboru</i18nString> </i18n> <i18n locale="de"> - <i18nString name="import_filters">Import von Filtern</i18nString> - <i18nString name="upload_file">Filterdatei hochladen</i18nString> - <i18nString name="upload_file_placeholder">Datei mit Filtern einfügen</i18nString> - <i18nString name="upload_file_desc">Xml-Datei einfügen, die Filter enthält</i18nString> - <i18nString name="import_file_placeholder">Filter importieren</i18nString> - <i18nString name="import_file_desc">Filter aus hochgeladener xml-Datei importieren</i18nString> + <i18nString id="import_filters">Import von Filtern</i18nString> + <i18nString id="upload_file">Filterdatei hochladen</i18nString> + <i18nString id="upload_file_placeholder">Datei mit Filtern einfügen</i18nString> + <i18nString id="upload_file_desc">Xml-Datei einfügen, die Filter enthält</i18nString> + <i18nString id="import_file_placeholder">Filter importieren</i18nString> + <i18nString id="import_file_desc">Filter aus hochgeladener xml-Datei importieren</i18nString> </i18n> <!-- TRANSITIONS --> <transition> <id>importFilter</id> <x>200</x> <y>100</y> - <label name="import_file_placeholder">Import filters</label> - <layout> - <offset>0</offset> - </layout> + <title id="import_file_placeholder">Import filters auto - - DataGroup_0 - grid - - upload_file - - editable - - - 0 - 0 - 1 - 2 - 0 - - outline - - - - import_file - - editable - - importedFiltersRef: f.imported_filters; + + select_user_grid + + + upload_file + + editable + + + + 1 / 2 + + + + + import_file + + editable + + + import_file_importFilter_set + + + importedFiltersRef: f.imported_filters; - change importedFiltersRef value { importFilters() } - - - - 2 - 0 - 1 - 2 - 0 - - outline - - - - - DataGroup_1 - grid - - imported_filters - - editable - - - 0 - 1 - 1 - 4 - 0 - - outline - - - + change importedFiltersRef value { importFilters() } + + + + + + 2 / 3 + + + + + divider_1 + + visible + + + + 1 / span 2 + + + + + imported_filters + + editable + + + + 1 / span 2 + + + + grid + repeat(2, 1fr) + stretch + stretch + stretch + stretch + + - + importFilter_finish importedFilters: f.imported_filters; - taskService.finishTasks(taskService.findAllById(importedFilters.value), userService.getLoggedUser()) + taskService.finishTasks(taskService.findAllById(importedFilters.value), userService.getLoggedUser(), new HashMap<>()) change importedFilters value { [] } - + importFilter_cancel importedFilters: f.imported_filters; taskService.findAllById(importedFilters.value).forEach({filterTask -> - workflowService.deleteCase(filterTask.caseId) + deleteCase(filterTask.caseId) }) change importedFilters value { [] } @@ -160,9 +183,7 @@ p1 100 100 - 1 - false @@ -179,4 +200,4 @@ p1 1 - + diff --git a/src/main/resources/petriNets/engine-processes/org_group.xml b/src/main/resources/petriNets/engine-processes/org_group.xml deleted file mode 100644 index 67a91e1a48d..00000000000 --- a/src/main/resources/petriNets/engine-processes/org_group.xml +++ /dev/null @@ -1,961 +0,0 @@ - - - org_group - 1.0.0 - GRP - Organization group - home - true - false - - - - - - - { - com.netgrif.application.engine.workflow.domain.Case useCase -> - - def cases = findCasesElastic( - "processIdentifier:\"preference_filter_item\" AND dataSet.parentId.textValue.keyword:\"$useCase.stringId\"" as String, - org.springframework.data.domain.PageRequest.of(0, 1000)) - change availableEntries options { return menuImportExportService.createAvailableEntriesChoices(cases) } - } - - - system - System - - - - group_id - Group ID - Enter group ID - ID of organization group - - id: f.group_id; - change id value { useCase.stringId } - - - - author - Group Author - - - group_name - Group name - Enter group name - Name of organization group - - name: f.group_name; - useCase.setTitle(name.value.value) - workflowService.save(useCase) - - - - user_selection - Select user - No user selected - Select user to be added as a group member - - userField: f.user_selection; - change userField value { null } - - - selection: f.members, - userField: f.user_selection; - change selection options { nextGroupService.addUser(userField.value.value, selection.options) } - - - - members - Members - Members of current organization group - - list - - - - user_action_selection - Select action - - - - - add - - action_selection: f.user_action_selection, - user_selection: f.user_selection, - invite_by_mail: f.invite_by_mail, - trans: t.8; - - make user_selection, editable on trans when { action_selection.value.value == "add" } - make invite_by_mail, hidden on trans when { action_selection.value.value == "add" } - - make user_selection, hidden on trans when { action_selection.value.value == "invite" } - make invite_by_mail, editable on trans when { action_selection.value.value == "invite" } - - - - invite_by_mail - Add e-mail address - example@example.com - Add e-meail address to send invitation - - - email - - - - - - imported_menu_ids - - - - export_menu_file - Exported menu file - Your XML file with menus - Download exported file with menus in XML format. - - - update_available_entries_btn - - Update entries - - availableEntries: f.available_export_entries; - - updateAvailableEntries(useCase) - - - - clear_menu_selection_btn - - Clear menu configurations - - menusForExport: f.menus_for_export; - - change menusForExport options {[:]} - - - - export_menu_name - Exported menu identifier - Unique name menu configuration for selected entries. - - addToExportBtn: f.add_to_export_btn, - exportMenuName: f.this, - trans: t.navigationMenuConfig; - - if (exportMenuName.value.value == "") { - make addToExportBtn, visible on trans when {true} - } else { - make addToExportBtn, editable on trans when {true} - } - - - - available_export_entries - Available entries for export - Export menu - - - add_to_export_btn - - Add entries to export - - selectedEntries: f.available_export_entries, - addToExportBtn: f.this, - menuIdentifier: f.export_menu_name, - menusForExport: f.menus_for_export; - - change menusForExport options { return menuImportExportService.addSelectedEntriesToExport(selectedEntries, menusForExport, menuIdentifier.value.value) } - - change selectedEntries value {[]} - - - raised - - - - menus_for_export - Menus to be exported - - - import_results - Import results - - area - - - - export_menu_btn - - <placeholder name="export_menu_btn_placeholder">Export menu</placeholder> - <action trigger="set"> - export_file: f.export_menu_file, - menuIdentifier: f.export_menu_name, - menusForExport: f.menus_for_export, - groupId: f.group_id; - - change export_file value { menuImportExportService.exportMenu(menusForExport, groupId.value.value, export_file) } - change menusForExport options {[:]} - </action> - <component> - <name>raised</name> - </component> - </data> - <data type="file"> - <id>import_menu_file</id> - <title>Import menu - Menu file to import - Upload XML file containing menu here - - - import_menu_btn - - <placeholder name="import_menu_btn_placeholder">Import menu</placeholder> - <desc name="import_menu_btn_desc">Import menu from provided XML file</desc> - <action trigger="set"> - import_file: f.import_menu_file, - groupId: f.group_id, - newEntries: f.imported_menu_ids, - newIdsActionSetter: f.new_entries_setter, - importResults: f.import_results; - - change importResults value {return ""} - - def cases = findCases({ it.processIdentifier.eq("preference_filter_item") }).findAll { it.dataSet.get("parentId").rawValue == useCase.stringId } - change newEntries value { return menuImportExportService.importMenu(cases, import_file.value.value, useCase.stringId) } - // TODO: release/8.0.0 remove? - def actualUseCase = findCase(useCase.stringId) - actualUseCase.dataSet.entrySet().forEach{ e -> - useCase.dataSet[e.key].value.value = e.value.value - if(e.key == ("imported_menu_ids")) { - useCase.dataSet[e.key].value.value = newEntries.value.value - } - } - - change newIdsActionSetter value { "triggerAction" } - </action> - <component> - <name>raised</name> - </component> - </data> - <data type="text"> - <id>new_entries_setter</id> - <title/> - <action trigger="set"> - import_file: f.import_menu_file, - groupId: f.group_id, - newEntries: f.imported_menu_ids, - availableEntries: f.available_export_entries, - importResults: f.import_results; - - // TODO: release/8.0.0 check - newEntries.value.forEach { itemId -> - def idSplit = itemId.split(',') - def initTask = findTask({it.transitionId.eq("init").and(it.caseId.eq(idSplit[0]))}) - - setData(initTask, [ - "filter_case": ["type":"caseRef", "value": [idSplit[1]], "allowedNets":["filter"]], - "use_icon": ["type":"boolean", "value": idSplit[2]] - ]) - } - - finishTask(initTask) - - workflowService.save(useCase) - - updateAvailableEntries(useCase) - </action> - </data> - <!-- I18NS --> - <i18n locale="sk"> - <i18nString name="author">Autor grupy</i18nString> - <i18nString name="group_id">ID grupy</i18nString> - <i18nString name="group_id_desc">ID organizačnej grupy</i18nString> - <i18nString name="group_id_placeh">Zadajte ID grupy</i18nString> - <i18nString name="group_name">Názov grupy</i18nString> - <i18nString name="group_name_desc">Názov organizačnej grupy</i18nString> - <i18nString name="group_name_placeh">Zadajte názov grupy</i18nString> - <i18nString name="user_selection">Vyberte nového používateľa</i18nString> - <i18nString name="user_selection_desc">Vyberte nového používateľa pre pridanie do grupy</i18nString> - <i18nString name="user_selection_placeh">Nebol vybraný žiadny používateľ</i18nString> - <i18nString name="members">Členovia grupy</i18nString> - <i18nString name="members_desc">Členovia organizačnej grupy</i18nString> - <i18nString name="user_action_selection">Vyberte akciu</i18nString> - <i18nString name="user_action_selection_add">Pridať existujúceho používateľa</i18nString> - <i18nString name="user_action_selection_invite">Pozvať nového používateľa</i18nString> - <i18nString name="invite_by_mail">Zadaj e-mail adresu</i18nString> - <i18nString name="invite_by_mail_desc">Zadaj e-mail adresu</i18nString> - <i18nString name="select_menu_item_filter">Zvoľte filter</i18nString> - <i18nString name="add_menu_item">Pridať ako položku menu</i18nString> - <i18nString name="menu_configuration">Konfigurácia menu</i18nString> - <i18nString name="export_file">Exportovaný súbor s menu</i18nString> - <i18nString name="export_file_desc">Stiahnite exportovaný XML súbor s menu položkami.</i18nString> - <i18nString name="export_file_placeholder">Váš XML súbor s vybranou menu konfiguráciou.</i18nString> - <i18nString name="exported_menu_id">Identifikátor menu nakonfigurovaného na export</i18nString> - <i18nString name="exported_menu_id_desc">Unikátny názov menu pre zvolenú konfiguráciu.</i18nString> - <i18nString name="available_export_entries">Dostupné menu položky pre export</i18nString> - <i18nString name="available_export_entries_placeholder">Export menu</i18nString> - <i18nString name="add_to_export_placeholder">Pridať menu na export</i18nString> - <i18nString name="menus_for_export">Menu položky pripravené na export</i18nString> - <i18nString name="import_results">Výsledky importu</i18nString> - <i18nString name="export_menu_btn_placeholder">Exportovať menu</i18nString> - <i18nString name="update_available_entries_btn_placeholder">Aktualizovať dostupné položky</i18nString> - <i18nString name="clear_menu_selection_btn_placeholder">Zmazať vytvorené konfigurácie</i18nString> - <i18nString name="import_export_dg">Import a export položiek menu</i18nString> - </i18n> - <i18n locale="de"> - <i18nString name="select_menu_item_filter">Filter auswählen</i18nString> - <i18nString name="add_menu_item">Als Menüpunkt hinzufügen</i18nString> - <i18nString name="menu_configuration">Menükonfiguration</i18nString> - <i18nString name="export_file">Exportierte Datei mit Menüs</i18nString> - <i18nString name="export_file_desc">Exportierte XML-Datei mit Menüs herunterladen.</i18nString> - <i18nString name="export_file_placeholder">Ihre XML-Datei mit Menüs</i18nString> - <i18nString name="exported_menu_id">Name des für den Export konfigurierten Menüs</i18nString> - <i18nString name="exported_menu_id_desc">Eindeutiger Name des Menüs für die gewählte Konfiguration.</i18nString> - <i18nString name="available_export_entries">Verfügbare Menüeinträge für den Export</i18nString> - <i18nString name="available_export_entries_placeholder">Menü exportieren</i18nString> - <i18nString name="add_to_export_placeholder">Menü zum Export hinzufügen</i18nString> - <i18nString name="menus_for_export">Menüeinträge bereit für den Export</i18nString> - <i18nString name="import_results">Import Ergebnisse</i18nString> - <i18nString name="export_menu_btn_placeholder">Menü exportieren</i18nString> - <i18nString name="update_available_entries_btn_placeholder">Verfügbare Menüeinträge aktualisieren</i18nString> - <i18nString name="clear_menu_selection_btn_placeholder">Menükonfigurationen löschen</i18nString> - <i18nString name="import_export_dg">Import und Export von Menüeinträge</i18nString> - </i18n> - <!-- TRANSITIONS --> - <transition> - <id>2</id> - <x>220</x> - <y>220</y> - <layout> - <offset>0</offset> - </layout> - <label>Initialize group</label> - <assignPolicy>auto</assignPolicy> - <dataGroup> - <id>DataGroup_0</id> - <layout>grid</layout> - <dataRef> - <id>group_id</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>4</cols> - <offset>6</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>author</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>1</rows> - <cols>4</cols> - <offset>6</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>group_name</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>2</y> - <rows>1</rows> - <cols>4</cols> - <offset>6</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="finish"> - <id>1</id> - <actions phase="pre"> - <action> - <!--@formatter:off--> - availableEntries: f.available_export_entries; - // TODO: release/8.0.0 - defaultFilters = findDefaultFilters() - - defaultFilters.forEach { filterCase -> - def optionCase = createCase("preference_filter_item", filterCase.title + " filter preference") - - def initTask = findTask(optionCase.getTaskStringId("init")) - assignTask(initTask) - setData(initTask, new DataSet([ - "filter_case": new CaseField(rawValue: [filterCase.stringId], allowedNets: ["filter"]), - "parentId": new TextField(rawValue: useCase.stringId), - "menu_identifier": new TextField(rawValue: "defaultMenu") - ])) - finishTask(initTask) - } - - updateAvailableEntries(useCase) - <!--@formatter:on--> - </action> - </actions> - </event> - </transition> - <transition> - <id>6</id> - <x>740</x> - <y>100</y> - <layout> - <offset>0</offset> - </layout> - <label>Group info</label> - <assignPolicy>auto</assignPolicy> - <dataGroup> - <id>DataGroup_0</id> - <layout>grid</layout> - <dataRef> - <id>group_id</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>4</cols> - <offset>0</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>author</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>1</rows> - <cols>4</cols> - <offset>0</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>group_name</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>0</x> - <y>2</y> - <rows>1</rows> - <cols>4</cols> - <offset>0</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>members</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>0</x> - <y>3</y> - <rows>1</rows> - <cols>4</cols> - <offset>0</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - </transition> - <transition> - <id>8</id> - <x>500</x> - <y>340</y> - <layout> - <offset>0</offset> - </layout> - <label>Add user</label> - <assignPolicy>auto</assignPolicy> - <dataGroup> - <id>DataGroup_0</id> - <layout>grid</layout> - <dataRef> - <id>user_action_selection</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>2</rows> - <cols>4</cols> - <offset>6</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>user_selection</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>2</y> - <rows>1</rows> - <cols>4</cols> - <offset>6</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>invite_by_mail</id> - <logic> - <behavior>hidden</behavior> - </logic> - <layout> - <x>0</x> - <y>3</y> - <rows>1</rows> - <cols>4</cols> - <offset>6</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>members</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>0</x> - <y>4</y> - <rows>1</rows> - <cols>4</cols> - <offset>6</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="finish"> - <id>invite_new_user</id> - <actions phase="pre"> - <action> - action_selection: f.user_action_selection, - invite_by_mail: f.invite_by_mail, - members: f.members; - - if(action_selection.value.value == "invite" && invite_by_mail.value.value != null){ - change members options { nextGroupService.inviteUser(invite_by_mail.value.value, members.options, useCase) } - } - </action> - </actions> - </event> - </transition> - <transition> - <id>25</id> - <x>740</x> - <y>340</y> - <layout> - <offset>0</offset> - </layout> - <label>Edit group info</label> - <assignPolicy>auto</assignPolicy> - <dataGroup> - <id>DataGroup_0</id> - <layout>grid</layout> - <dataRef> - <id>group_id</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>4</cols> - <offset>6</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>author</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>1</rows> - <cols>4</cols> - <offset>6</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>group_name</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>2</y> - <rows>1</rows> - <cols>4</cols> - <offset>6</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - </transition> - <transition> - <id>28</id> - <x>500</x> - <y>100</y> - <layout> - <offset>0</offset> - </layout> - <label>Remove user</label> - <assignPolicy>auto</assignPolicy> - <dataGroup> - <id>DataGroup_0</id> - <layout>grid</layout> - <dataRef> - <id>members</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>4</cols> - <offset>6</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="finish"> - <id>remove_user</id> - <actions phase="pre"> - <action> - members: f.members; - change members options { nextGroupService.removeUser(members.value.value, members.options, useCase) } - change members value { [] } - </action> - </actions> - </event> - </transition> - <transition> - <id>navigationMenuConfig</id> - <x>380</x> - <y>100</y> - <layout> - <cols>5</cols> - <offset>0</offset> - </layout> - <label name="menu_configuration">Configure menu</label> - <assignPolicy>auto</assignPolicy> - <dataGroup> - <id>dg2</id> - <layout>grid</layout> - <title name="import_export_dg">Import & export of menu entries - - available_export_entries - - editable - - - 0 - 0 - 1 - 1 - 0 - - outline - - - - export_menu_name - - editable - - - 1 - 0 - 1 - 2 - 0 - - outline - - - - update_available_entries_btn - - editable - - - 3 - 0 - 1 - 1 - 0 - - outline - - - - add_to_export_btn - - visible - - - 4 - 0 - 1 - 1 - 0 - - outline - - - - menus_for_export - - editable - - - 0 - 1 - 1 - 3 - 0 - - outline - - - - clear_menu_selection_btn - - editable - - - 3 - 1 - 1 - 1 - 0 - - outline - - - - export_menu_btn - - editable - - - 4 - 1 - 1 - 1 - 0 - - outline - - - - export_menu_file - - visible - - - 0 - 2 - 1 - 3 - 0 - - outline - - - - import_menu_file - - editable - - - 0 - 3 - 1 - 3 - 0 - - outline - - - - import_menu_btn - - editable - - - 4 - 3 - 1 - 1 - 0 - - outline - - - - import_results - - visible - - - 0 - 4 - 1 - 5 - 0 - - outline - - - - - - - - 1 - 100 - 220 - - 1 - false - - - 4 - 620 - 220 - - 0 - false - - - p1 - 300 - 100 - - 0 - false - - - - 3 - regular - 1 - 2 - 1 - - - 5 - regular - 2 - 4 - 1 - - - 18 - read - 4 - 6 - 1 - - - 21 - regular - 4 - 8 - 1 - - - 22 - regular - 8 - 4 - 1 - - - 26 - regular - 4 - 25 - 1 - - - 27 - regular - 25 - 4 - 1 - - - 29 - regular - 28 - 4 - 1 - - - 30 - regular - 4 - 28 - 1 - - - a3 - regular - 2 - p1 - 1 - - - a5 - read - p1 - navigationMenuConfig - 1 - - diff --git a/src/main/resources/petriNets/engine-processes/preference_filter_item.xml b/src/main/resources/petriNets/engine-processes/preference_filter_item.xml index 19e478ba7bd..c806f11d472 100644 --- a/src/main/resources/petriNets/engine-processes/preference_filter_item.xml +++ b/src/main/resources/petriNets/engine-processes/preference_filter_item.xml @@ -1,952 +1,804 @@ - - + preference_filter_item - PFI + 1.0.0 Preference filter item list true - false - - - - - - - menu_identifier - Identifier of menu which is this menu entry part of. - default + false + + PFI + + + + + add_allowed_roles + + <placeholder id="allow_roles">Allow view for roles</placeholder> + <event type="set"> + <actions phase="post"> + <action id="action_4"> + <![CDATA[ + change allowed_roles options {return configurableMenuService.addSelectedRoles(allowed_roles, processes_available, roles_available)} + change roles_available value {[]} + change roles_available options {[:]} + change processes_available value {null} + ]]> + </action> + </actions> + </event> </data> - <data type="enumeration" immediate="true"> - <id>entry_name</id> - <title> + + add_banned_roles + + <placeholder id="ban_roles">Ban view for roles</placeholder> + <event type="set"> + <actions phase="post"> + <action id="action_6"> + <![CDATA[ + change banned_roles options {return configurableMenuService.addSelectedRoles(banned_roles, processes_available, roles_available)} + change roles_available value {[]} + change roles_available options {[:]} + change processes_available value {null} + ]]> + </action> + </actions> + </event> </data> - <data type="text" > - <id>entry_default_name</id> - <title name="menu_item_title">Menu item title + + allowed_nets + Allowed nets - - entry_marker - + + allowed_roles + Allowed roles + List of roles allowed to view this menu entry. - - move_option_up - - Up - - parentId: f.parentId; - - if (!task.isPresent()) { - return - } - - def parentCase = findCase({it.id.eq(new org.bson.types.ObjectId(parentId.value.value))}); - - def previousTaskRefValue = parentCase.dataSet.get("filter_tasks").value.value - - def currentIndex = previousTaskRefValue.findIndexOf({ id -> id == task.get().stringId}) - - if (currentIndex != 0) { - previousTaskRefValue.remove(currentIndex) - previousTaskRefValue.add(currentIndex - 1, task.get().stringId) - - def parentTask = findTask({it.caseId.eq(parentId.value.value).and(it.transitionId.eq("navigationMenuConfig"))}) - def dataSet = new com.netgrif.application.engine.workflow.web.responsebodies.DataSet([ - "filter_tasks" : new com.netgrif.application.engine.petrinet.domain.dataset.TaskField(rawValue: previousTaskRefValue), - ]) - setDataWithPropagation(parentTask, dataSet) - } - + + banned_roles + Banned roles + List of roles not allowed to view this menu entry. - - move_option_down - - Down - - parentId: f.parentId; - - if (!task.isPresent()) { - return; - } - - def parentCase = findCase({it.id.eq(new org.bson.types.ObjectId(parentId.value.value))}); - - def previousTaskRefValue = parentCase.dataSet.get("filter_tasks").value.value - - def currentIndex = previousTaskRefValue.findIndexOf({ id -> id == task.get().stringId}) - - if (currentIndex != previousTaskRefValue.size() - 1) { - previousTaskRefValue.remove(currentIndex) - previousTaskRefValue.add(currentIndex + 1, task.get().stringId) - - def parentTask = findTask({it.caseId.eq(parentId.value.value).and(it.transitionId.eq("navigationMenuConfig"))}) - def dataSet = new com.netgrif.application.engine.workflow.web.responsebodies.DataSet([ - "filter_tasks" : new com.netgrif.application.engine.petrinet.domain.dataset.TaskField(rawValue: previousTaskRefValue), - ]) - setDataWithPropagation(parentTask, dataSet) - } - + + create_case_button_icon + "New case" button icon identifier + + + + """} + return; + } + change create_case_button_icon_preview value { + """""" + create_case_button_icon.rawValue + """""" + } + ]]> + + + - - remove_option - - Remove - - - - parentId: f.parentId, - filterCase: f.filter_case; - - if (!task.isPresent()) { - return; - } - def parentCase = findCase({ it.id.eq(new org.bson.types.ObjectId(parentId.value.value)) }); - def previousTaskRefValue = parentCase.dataSet.get("filter_tasks").value.value - def currentIndex = previousTaskRefValue.findIndexOf({ id -> id == task.get().stringId }) - - previousTaskRefValue.remove(currentIndex) - - def previousCaseRefValue = parentCase.dataSet.get("referenced_filters").value.value - currentIndex = previousCaseRefValue.findIndexOf({ id -> id == filterCase.value.value[0] }) - previousCaseRefValue.remove(currentIndex) - - def parentTask = findTask({ it.caseId.eq(parentId.value.value).and(it.transitionId.eq("navigationMenuConfig")) }) - def dataSet = new com.netgrif.application.engine.workflow.web.responsebodies.DataSet([ - "filter_tasks" : new com.netgrif.application.engine.petrinet.domain.dataset.TaskField(rawValue: previousTaskRefValue), - "referenced_filters": new com.netgrif.application.engine.petrinet.domain.dataset.CaseField(rawValue: previousCaseRefValue), - ]) - setDataWithPropagation(parentTask, dataSet) - async.run { - workflowService.deleteCase(useCase.stringId) - } - - + + create_case_button_icon_preview + Menu icon preview + + htmltextarea + - - filter_preview - + + create_case_button_title + "New case" button title + + + default_headers + Set default headers + + + entry_default_name + Menu item title + + + entry_marker + + </data> + <data type="enumeration" immediate="true"> + <id>entry_name</id> + <title/> </data> <data type="caseRef"> <id>filter_case</id> - <title> + <allowedNets> <allowedNet>filter</allowedNet> </allowedNets> </data> - <data type="text" immediate="true"> - <id>parentId</id> - <title> + + filter_preview + </data> - <data type="boolean" immediate="true"> - <id>use_icon</id> - <title name="display_icon">Display menu icon? - true + + icon_name + Menu icon identifier + Material icon identifier. List of icons with identifiers is available online. + + + + """} + return; + } + change icon_preview value { + """""" + icon_name.rawValue + """""" + } + ]]> + + + icon_preview - Menu icon preview + Menu icon preview - htmltextarea + htmltextarea - + + + menu_identifier + Identifier of menu which is this menu entry part of. + default - icon_name - Menu icon identifier - Material icon identifier. List of icons with identifiers is available online. - - iconIdentifier: f.this, - iconPreview: f.icon_preview; - - if (iconIdentifier.value.value == "") { - change iconPreview value {"""]]>} - return; - } - - change iconPreview value { - """]]> + iconIdentifier.value.value + """]]> - } - + menu_item_identifier + Identifikátor (Filter API) - add_allowed_roles - - Allow view for roles - - allowedRoles: f.allowed_roles, - processesAvailable: f.processes_available, - rolesAvailable: f.roles_available; - - change allowedRoles options {return configurableMenuService.addSelectedRoles(allowedRoles, processesAvailable, rolesAvailable)} - - change rolesAvailable value {[]} - change rolesAvailable options {[:]} - change processesAvailable value {null} - + move_option_down + + <placeholder id="move_down">Down</placeholder> + <event type="set"> + <actions phase="post"> + <action id="action_1"> + <![CDATA[ + if (!task.isPresent()) { + return; + } + def parentCase = findCase({it.id.eq(new org.bson.types.ObjectId(parentId.rawValue))}); + def previousTaskRefValue = parentCase.dataSet.get("filter_tasks").rawValue + def currentIndex = previousTaskRefValue.findIndexOf({ id -> id == task.get().stringId}) + if (currentIndex != previousTaskRefValue.size() - 1) { + previousTaskRefValue.remove(currentIndex) + previousTaskRefValue.add(currentIndex + 1, task.get().stringId) + def parentTask = findTask({it.caseId.eq(parentId.rawValue).and(it.transitionId.eq("navigationMenuConfig"))}) + def dataSet = new com.netgrif.application.engine.workflow.web.responsebodies.DataSet([ + "filter_tasks" : new com.netgrif.application.engine.petrinet.domain.dataset.TaskField(rawValue: previousTaskRefValue), + ]) + setDataWithPropagation(parentTask, dataSet) + } + ]]> + </action> + </actions> + </event> </data> <data type="button"> - <id>remove_allowed_roles</id> - <title> - Remove from allowed roles - - allowedRoles: f.allowed_roles, - processesAvailable: f.processes_available, - rolesAvailable: f.roles_available; - - change allowedRoles options {return configurableMenuService.removeSelectedRoles(allowedRoles)} - - change allowedRoles value {[]} - change rolesAvailable value {[]} - change rolesAvailable options {[:]} - change processesAvailable value {null} - + move_option_up + + <placeholder id="move_up">Up</placeholder> + <event type="set"> + <actions phase="post"> + <action id="action_0"> + <![CDATA[ + if (!task.isPresent()) { + return + } + def parentCase = findCase({it.id.eq(new org.bson.types.ObjectId(parentId.rawValue))}); + def previousTaskRefValue = parentCase.dataSet.get("filter_tasks").rawValue + def currentIndex = previousTaskRefValue.findIndexOf({ id -> id == task.get().stringId}) + if (currentIndex != 0) { + previousTaskRefValue.remove(currentIndex) + previousTaskRefValue.add(currentIndex - 1, task.get().stringId) + def parentTask = findTask({it.caseId.eq(parentId.rawValue).and(it.transitionId.eq("navigationMenuConfig"))}) + def dataSet = new com.netgrif.application.engine.workflow.web.responsebodies.DataSet([ + "filter_tasks" : new com.netgrif.application.engine.petrinet.domain.dataset.TaskField(rawValue: previousTaskRefValue), + ]) + setDataWithPropagation(parentTask, dataSet) + } + ]]> + </action> + </actions> + </event> </data> - <data type="button"> - <id>add_banned_roles</id> - <title> - Ban view for roles - - bannedRoles: f.banned_roles, - processesAvailable: f.processes_available, - rolesAvailable: f.roles_available; - - change bannedRoles options {return configurableMenuService.addSelectedRoles(bannedRoles, processesAvailable, rolesAvailable)} - - change rolesAvailable value {[]} - change rolesAvailable options {[:]} - change processesAvailable value {null} - + + new_filter_id + </data> - <data type="button"> - <id>remove_banned_roles</id> - <title> - Remove from banned roles - - bannedRoles: f.banned_roles, - processesAvailable: f.processes_available, - rolesAvailable: f.roles_available; - - change bannedRoles options {return configurableMenuService.removeSelectedRoles(bannedRoles)} - - change bannedRoles value {[]} - change rolesAvailable value {[]} - change rolesAvailable options {[:]} - change processesAvailable value {null} - + + parentId + </data> <data type="enumeration_map" immediate="true"> <id>processes_available</id> - <title name="available_processes">Your processes - Select a process containing roles you wish to add to allowed or banned roles lists. - - processes: f.this; - - change processes options {return configurableMenuService.getNetsByAuthorAsMapOptions(loggedUser(), org.springframework.context.i18n.LocaleContextHolder.locale)} - - - processes: f.this, - allowedRoles: f.allowed_roles, - bannedRoles: f.banned_roles, - rolesAvailable: f.roles_available; - - change rolesAvailable options {return configurableMenuService.getAvailableRolesFromNet(processes, allowedRoles, bannedRoles)} - change rolesAvailable value {[]} - - - - roles_available - Available roles from selected process - - - allowed_roles - Allowed roles - List of roles allowed to view this menu entry. - - - banned_roles - Banned roles - List of roles not allowed to view this menu entry. + Your processes + Select a process containing roles you wish to add to allowed or banned roles lists. + + + + + + + + + + + + + + - - new_filter_id + + remove_allowed_roles + <placeholder id="remove_from_allowed_roles">Remove from allowed roles</placeholder> + <event type="set"> + <actions phase="post"> + <action id="action_5"> + <![CDATA[ + change allowed_roles options {return configurableMenuService.removeSelectedRoles(allowed_roles)} + change allowed_roles value {[]} + change roles_available value {[]} + change roles_available options {[:]} + change processes_available value {null} + ]]> + </action> + </actions> + </event> </data> - <data type="text" immediate="true"> - <id>menu_item_identifier</id> - <title>Identifikátor (Filter API) - - - create_case_button_title - "New case" button title + + remove_banned_roles + + <placeholder id="remove_from_banned_roles">Remove from banned roles</placeholder> + <event type="set"> + <actions phase="post"> + <action id="action_7"> + <![CDATA[ + change banned_roles options {return configurableMenuService.removeSelectedRoles(banned_roles)} + change banned_roles value {[]} + change roles_available value {[]} + change roles_available options {[:]} + change processes_available value {null} + ]]> + </action> + </actions> + </event> </data> - <data type="text" immediate="true"> - <id>create_case_button_icon_preview</id> - <title name="create_case_button_icon_preview">Menu icon preview - - htmltextarea - + + remove_option + + <placeholder id="remove">Remove</placeholder> + <event type="set"> + <actions phase="post"> + <action id="action_2"> + <![CDATA[ + if (!task.isPresent()) { + return; + } + def parentCase = findCase({ it.id.eq(new org.bson.types.ObjectId(parentId.rawValue)) }); + def previousTaskRefValue = parentCase.dataSet.get("filter_tasks").rawValue + def currentIndex = previousTaskRefValue.findIndexOf({ id -> id == task.get().stringId }) + previousTaskRefValue.remove(currentIndex) + def previousCaseRefValue = parentCase.dataSet.get("referenced_filters").rawValue + currentIndex = previousCaseRefValue.findIndexOf({ id -> id == filter_case.rawValue[0] }) + previousCaseRefValue.remove(currentIndex) + def parentTask = findTask({ it.caseId.eq(parentId.rawValue).and(it.transitionId.eq("navigationMenuConfig")) }) + def dataSet = new com.netgrif.application.engine.workflow.web.responsebodies.DataSet([ + "filter_tasks" : new com.netgrif.application.engine.petrinet.domain.dataset.TaskField(rawValue: previousTaskRefValue), + "referenced_filters": new com.netgrif.application.engine.petrinet.domain.dataset.CaseField(rawValue: previousCaseRefValue), + ]) + setDataWithPropagation(parentTask, dataSet) + async.run { + deleteCase(useCase.stringId) + } + ]]> + </action> + </actions> + </event> </data> - <data type="text" immediate="true"> - <id>create_case_button_icon</id> - <title name="create_case_button_icon">"New case" button icon identifier - - create_case_button_icon_preview: f.create_case_button_icon_preview, - create_case_button_icon: f.create_case_button_icon; - - - if (create_case_button_icon.value.value == "") { - change create_case_button_icon_preview value {"""]]>} - return; - } - - change create_case_button_icon_preview value { - """]]> + create_case_button_icon.value.value + """]]> - } - - - - - default_headers - Set default headers + + roles_available + Available roles from selected process - - - allowed_nets - Allowed nets + + use_icon + Display menu icon? + true - - - - - - - - - - - - - - - - - - - - Názov položky menu - Posunúť nahor - Posunúť nadol - Odstrániť - Zobrazovať ikonu? - Náhľad ikony - Identifikátor ikony - Identifikátor Material ikony. Zoznam ikon s identifikátormi je dostupný online. - Pridaj k povoleným roliam - Odstráň z povolených rolí - Pridaj k zakázaným roliam - Odstráň zo zakázaných rolí - Vaše procesy - Vyberte proces obsahujúci roly ktoré chcete pridať do zoznamu povolených alebo zakázaných rolí. - Dostupné roly - Povolené roly - Zoznam rolí ktoré budú upravovaný menu záznam vidieť. - Zakázané roly - Zoznam rolí pre ktoré bude upravovaný menu záznam skrytý. - Názov tlačidla "Nová inštancia" - Identifikátor ikony tlačidla "Nová inštancia" - Náhľad ikony - Predvolené hlavičky + Názov položky menu + Posunúť nahor + Posunúť nadol + Odstrániť + Zobrazovať ikonu? + Náhľad ikony + Identifikátor ikony + Identifikátor Material ikony. Zoznam ikon s identifikátormi je dostupný online. + Pridaj k povoleným roliam + Odstráň z povolených rolí + Pridaj k zakázaným roliam + Odstráň zo zakázaných rolí + Vaše procesy + Vyberte proces obsahujúci roly ktoré chcete pridať do zoznamu povolených alebo zakázaných rolí. + Dostupné roly + Povolené roly + Zoznam rolí ktoré budú upravovaný menu záznam vidieť. + Zakázané roly + Zoznam rolí pre ktoré bude upravovaný menu záznam skrytý. + Názov tlačidla "Nová inštancia" + Identifikátor ikony tlačidla "Nová inštancia" + Náhľad ikony + Predvolené hlavičky - Menüpunkttitel - nach oben - nach unten - entfernen - Menüikone anzeigen - Ikonevorschau - Ikone ID - Material Ikone ID. Liste den Ikonen mit IDs ist online verfügbar. - Zu zulässigen Rollen hinzufügen - Aus zulässigen Rollen entfernen - Zu verbotenen Rollen hinzufügen - Aus verbotenen Rollen entfernen - Ihre Prozesse - Wählen Sie einen Prozess mit Rollen aus, die Sie zu Listen mit zulässigen oder verbotenen Rollen hinzufügen möchten. - Verfügbare Rollen - Zulässige Rollen - Liste der Rollen, die diesen Menüeintrag anzeigen dürfen. - Verbotene Rollen - Liste der Rollen, die diesen Menüeintrag nicht anzeigen dürfen. - Schaltflächentitel "Neuer Fall" - Ikone ID - Ikonevorschau - Anzuzeigende Attributmenge auswählen + Menüpunkttitel + nach oben + nach unten + entfernen + Menüikone anzeigen + Ikonevorschau + Ikone ID + Material Ikone ID. Liste den Ikonen mit IDs ist online verfügbar. + Zu zulässigen Rollen hinzufügen + Aus zulässigen Rollen entfernen + Zu verbotenen Rollen hinzufügen + Aus verbotenen Rollen entfernen + Ihre Prozesse + Wählen Sie einen Prozess mit Rollen aus, die Sie zu Listen mit zulässigen oder verbotenen Rollen hinzufügen möchten. + Verfügbare Rollen + Zulässige Rollen + Liste der Rollen, die diesen Menüeintrag anzeigen dürfen. + Verbotene Rollen + Liste der Rollen, die diesen Menüeintrag nicht anzeigen dürfen. + Schaltflächentitel "Neuer Fall" + Ikone ID + Ikonevorschau + Anzuzeigende Attributmenge auswählen - + + change_filter + 420 + 350 + [Change filter] + + change_filter_flex + + + new_filter_id + + editable + true + + + set_event_0 + + + + + + + + + 0 + 0 + 1 + + + + init 420 260 - - 0 - - - - filter_case - - forbidden - - - 1 - 0 - 1 - 2 - - - - - filterTaskRef: f.filter_preview, - filterCaseRef: f.filter_case, - entryDefaultName: f.entry_default_name, - entryName: f.entry_name, - icon: f.icon_name; - - def filterCase = findCase({it.id.eq(filterCaseRef.value.value[0])}) - - change entryDefaultName value {return filterCase.title} - - change entryName value {return filterCase.dataSet["i18n_filter_name"].value.value} - - change filterTaskRef value {return [findTask({it.caseId.eq(filterCase.stringId).and(it.transitionId.eq("view_filter"))}).stringId]} - - change icon value {filterCase.icon} - - - - - parentId - - editable - - - - icon_name - - editable - - + + <flex> + <id>init_flex</id> + <item> + <dataRef> + <id>filter_case</id> + <logic> + <behavior>forbidden</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>parentId</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>icon_name</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + </flex> </transition> <transition> <id>view</id> <x>660</x> <y>260</y> - <layout> - <cols>5</cols> - <offset>0</offset> - </layout> - <label></label> - <dataGroup> - <id>DataGroup_0</id> - <title> - grid - - entry_default_name - - editable - - entryName: f.entry_name, - filterTask: f.filter_preview, - filterCaseRef: f.filter_case, - entryDefaultName: f.entry_default_name; - - def filterCase = findCase({it.id.eq(new org.bson.types.ObjectId(filterCaseRef.value.value[0]))}) - filterCase.setTitle(entryDefaultName.value.value) - workflowService.save(filterCase) - def filterTask = findTask({ it.id.eq(filterTask.value.value[0])}) - setData(filterTask, [ - "new_title": ["type":"text", "value": entryDefaultName.value.value] - ]) - - change entryName value {return new com.netgrif.application.engine.petrinet.domain.I18nString(entryDefaultName.value.value)} - - - - 0 - 0 - 1 - 2 - 0 - - outline - - - - move_option_up - - editable - - - 2 - 0 - 1 - 1 - 0 - - fill - - - - move_option_down - - editable - - - 3 - 0 - 1 - 1 - 0 - - - - - remove_option - - editable - - - 4 - 0 - 1 - 1 - 0 - - - - - processes_available - - editable - - - 0 - 1 - 2 - 1 - 0 - - outline - - - - roles_available - - editable - - - 1 - 1 - 2 - 1 - 0 - - outline - - - - add_allowed_roles - - editable - - - 2 - 1 - 1 - 1 - 0 - - - - - allowed_roles - - editable - - - 3 - 1 - 1 - 1 - 0 - - outline - - - - remove_allowed_roles - - editable - - - 4 - 1 - 1 - 1 - 0 - - - - - add_banned_roles - - editable - - - 2 - 2 - 1 - 1 - 0 - - - - - banned_roles - - editable - - - 3 - 2 - 1 - 1 - 0 - - outline - - - - remove_banned_roles - - editable - - - 4 - 2 - 1 - 1 - 0 - - - - - use_icon - - editable - - - 0 - 3 - 1 - 1 - 0 - - - - 0 - - - trans: t.this, - iconPreview: f.icon_preview, - iconName: f.icon_name, - useIcon: f.use_icon; - - make iconPreview,visible on trans when {useIcon.value.value} - make iconName,editable on trans when {useIcon.value.value} - - make iconPreview,hidden on trans when {!useIcon.value.value} - make iconName,hidden on trans when {!useIcon.value.value} - - - - - - icon_preview - - visible - - - 1 - 3 - 1 - 1 - 0 - - - - icon_name - - editable - - iconIdentifier: f.icon_name, - filterCaseId: f.filter_case; - - def filterCase = findCase({it.id.eq(new org.bson.types.ObjectId(filterCaseId.value.value[0]))}) - filterCase.setIcon(iconIdentifier.value.value) - workflowService.save(filterCase) - - - - 2 - 3 - 1 - 2 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - filter_preview - - editable - - - 0 - 3 - 1 - 5 - 0 - - outline - - - - entry_marker - - hidden - - - 0 - 4 - 1 - 1 - 0 - - - - - - entry_name - - hidden - - - 1 - 4 - 1 - 1 - 0 - - - - - - create_case_button_title - - editable - - - 0 - 5 - 1 - 2 - 0 - - outline - - - - create_case_button_icon_preview - - visible - - - 2 - 5 - 1 - 1 - 0 - - outline - - - - create_case_button_icon - - editable - - - 3 - 5 - 1 - 2 - 0 - - outline - - - - default_headers - - editable - - - 0 - 6 - 1 - 4 - 0 - - outline - - - - - - - change_filter - 420 - 350 - - - - new_filter_id - - editable - required - - - set_event_0 - - - new_filter_id: f.new_filter_id, - filterTaskRef: f.filter_preview, - filterCaseRef: f.filter_case, - entryDefaultName: f.entry_default_name, - entryName: f.entry_name, - icon: f.icon_name; - - change filterCaseRef value { [new_filter_id.value.value] } - def filterCase = findCase({it.id.eq(filterCaseRef.value.value[0])}) - - change entryDefaultName value {return filterCase.title} - - change entryName value {return filterCase.dataSet["i18n_filter_name"].value.value} - - change filterTaskRef value {return [findTask({it.caseId.eq(filterCase.stringId).and(it.transitionId.eq("view_filter"))}).stringId]} - - change icon value {filterCase.icon} - - - - + + <flex> + <id>view_flex</id> + <item> + <dataRef> + <id>entry_default_name</id> + <logic> + <behavior>editable</behavior> + </logic> + <event type="set"> + <actions phase="post"> + <action id="action_11"> + <![CDATA[ + def filterCase = findCase({it.id.eq(new org.bson.types.ObjectId(filter_case.rawValue[0]))}) + filterCase.setTitle(entry_default_name.rawValue) + workflowService.save(filterCase) + def filter_preview = findTask({ it.id.eq(filter_preview.rawValue[0])}) + setData(filter_preview, [ + "new_title": ["type":"text", "value": entry_default_name.rawValue] + ]) + change entry_name value {return new com.netgrif.application.engine.petrinet.domain.I18nString(entry_default_name.rawValue)} + ]]> + </action> + </actions> + </event> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>move_option_up</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>move_option_down</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>remove_option</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>processes_available</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>roles_available</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>add_allowed_roles</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>allowed_roles</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>remove_allowed_roles</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>add_banned_roles</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>banned_roles</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>remove_banned_roles</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>use_icon</id> + <logic> + <behavior>editable</behavior> + </logic> + <event type="set"> + <id>0</id> + <actions phase="post"> + <action id="action_12"> + <![CDATA[ + make icon_preview,visible on this when {use_icon.rawValue} + make icon_name,editable on this when {use_icon.rawValue} + make icon_preview,hidden on this when {!use_icon.rawValue} + make icon_name,hidden on this when {!use_icon.rawValue} + ]]> + </action> + </actions> + </event> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>icon_preview</id> + <logic> + <behavior>visible</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>icon_name</id> + <logic> + <behavior>editable</behavior> + </logic> + <event type="set"> + <actions phase="post"> + <action id="action_13"> + <![CDATA[ + def filterCase = findCase({it.id.eq(new org.bson.types.ObjectId(filter_case.rawValue[0]))}) + filterCase.setIcon(icon_name.rawValue) + workflowService.save(filterCase) + ]]> + </action> + </actions> + </event> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>filter_preview</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>entry_marker</id> + <logic> + <behavior>hidden</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>entry_name</id> + <logic> + <behavior>hidden</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>create_case_button_title</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>create_case_button_icon_preview</id> + <logic> + <behavior>visible</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>create_case_button_icon</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>default_headers</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + </flex> </transition> - <!-- PLACES --> <place> <id>p1</id> <x>300</x> <y>260</y> - <label></label> <tokens>1</tokens> - <static>false</static> </place> <place> <id>p2</id> <x>540</x> <y>260</y> - <label></label> <tokens>0</tokens> - <static>false</static> </place> - <!-- ARCS --> <arc> <id>a4</id> <type>regular</type> @@ -975,4 +827,4 @@ <destinationId>change_filter</destinationId> <multiplicity>1</multiplicity> </arc> -</document> +</process> \ No newline at end of file diff --git a/src/main/resources/petriNets/engine-processes/preference_item.xml b/src/main/resources/petriNets/engine-processes/preference_item.xml index bd83d21b85d..4f6d98e0c8d 100644 --- a/src/main/resources/petriNets/engine-processes/preference_item.xml +++ b/src/main/resources/petriNets/engine-processes/preference_item.xml @@ -1,2665 +1,2551 @@ -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> - <id>preference_item</id> - <initials>PRI</initials> - <title>Preference Item - check_box_outline_blank - true - false - false - - system - - true - true - true - - - - admin - - true - true - true - - - - default - - false - false - true - - - - - preference_item_delete - - - removeItemChildCases(useCase) + + preference_item + 1.0.0 + Preference Item + check_box_outline_blank + true + false + + PRI + + + admin + + true + true + true + + + + defaultRole + + false + false + true + + + + system + + true + true + true + + + + + + preference_item_delete + + + - - - - - system - System - - - admin - Admin - - - { com.netgrif.application.engine.workflow.domain.Case useCase -> - - def childCaseIds = useCase.dataSet['childItemIds'].value - if (childCaseIds == null || childCaseIds.isEmpty()) { - return - } - - removeChildItemFromParent(useCase.dataSet['parentId'].value[0], useCase) - - def childCases = workflowService.findAllById(childCaseIds) - async.run { - childCases.each { - workflowService.deleteCase(it) - } - } + + + + + admin + Admin + + + system + System + + + + def childCaseIds = useCase.dataSet['childItemIds'].rawValue + if (childCaseIds == null || childCaseIds.isEmpty()) { + return + } + removeChildItemFromParent(useCase.dataSet['parentId'].rawValue[0], useCase) + def childCases = workflowService.findAllById(childCaseIds) + async.run { + childCases.each { + deleteCase(it) + } + } } - - + ]]> + + + - if (filterAutocomplete.getOptions().containsKey(filterAutocomplete.value)) { - change previewTaskRef value { - return [findTask({it.caseId.eq(filterAutocomplete.value).and(it.transitionId.eq("view_filter"))}).stringId] - } - make updateBtn,editable on trans when { true } - } else { - change filterAutocomplete options { - def findAllPredicate - if (taskTypeOnly) { - findAllPredicate = { filterCase -> - !selectedFilterRef.value.contains(filterCase.stringId) && - filterCase.dataSet["filter_type"].value == "Task" - } - } else { - findAllPredicate = { filterCase -> !selectedFilterRef.value.contains(filterCase.stringId) } - } - return findFilters(filterAutocomplete.value != null ? filterAutocomplete.value : "") - .findAll(findAllPredicate) - .collectEntries({filterCase -> [filterCase.stringId, filterCase.title]}) - } - change previewTaskRef value { [] } - make updateBtn,visible on trans when { true } - } + com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField filterAutocomplete, + com.netgrif.application.engine.petrinet.domain.dataset.TaskField previewTaskRef, + com.netgrif.application.engine.petrinet.domain.dataset.CaseField selectedFilterRef, + com.netgrif.application.engine.petrinet.domain.dataset.ButtonField updateBtn, + com.netgrif.application.engine.petrinet.domain.Transition trans, + boolean taskTypeOnly + -> + if (filterAutocomplete.getOptions()?.containsKey(filterAutocomplete.rawValue)) { + change previewTaskRef value { + return [findTask({it.caseId.eq(filterAutocomplete.rawValue).and(it.transitionId.eq("view_filter"))}).stringId] + } + make updateBtn,editable on trans when { true } + } else { + change filterAutocomplete options { + def findAllPredicate + if (taskTypeOnly) { + findAllPredicate = { filterCase -> + !selectedFilterRef.rawValue.contains(filterCase.stringId) && + filterCase.dataSet["filter_type"].rawValue == "Task" + } + } else { + findAllPredicate = { filterCase -> !selectedFilterRef.rawValue.contains(filterCase.stringId) } + } + return findFilters(filterAutocomplete.rawValue != null ? filterAutocomplete.rawValue : "") + .findAll(findAllPredicate) + .collectEntries({filterCase -> [filterCase.stringId, filterCase.title]}) + } + change previewTaskRef value { [] } + make updateBtn,visible on trans when { true } + } } - - + ]]> + + + - def existingOptions = optionsHolder.options - def selectedValues = valueSelector.value - def newOptions = [:] - - if (selectedValues != null) { - existingOptions.each { key, value -> - if (selectedValues.contains(key)) { - newOptions.put(key, value) - } - } - } - - if (!newOptions.containsKey(toBeUpdated.value)) { - change toBeUpdated value { null } - } - - change toBeUpdated options { newOptions } + com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField toBeUpdated, + com.netgrif.application.engine.petrinet.domain.dataset.MultichoiceMapField valueSelector, + com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField optionsHolder + -> + def existingOptions = optionsHolder.options + def selectedValues = valueSelector.rawValue + def newOptions = [:] + if (selectedValues != null) { + existingOptions.each { key, value -> + if (selectedValues.contains(key)) { + newOptions.put(key, value) + } + } + } + if (!newOptions.containsKey(toBeUpdated.rawValue)) { + change toBeUpdated value { null } + } + change toBeUpdated options { newOptions } } - - - - parentId - - <allowedNets> - <allowedNet>preference_item</allowedNet> - </allowedNets> - </data> - <data type="text"> - <id>move_previous_dest_uri</id> - <title/> - </data> - <data type="multichoice_map"> - <id>move_dest_uri</id> - <title name="move_dest_uri">Destination URI - List of nodes representing destination URI - - autocomplete - - - moveDestUri: f.move_dest_uri; - - String uriNodeId = elasticCaseService.findUriNodeId(useCase) - def node = uriService.findById(uriNodeId) - updateMultichoiceWithCurrentNode(moveDestUri, node) - - - prevDestUri: f.move_previous_dest_uri, - moveDestUri: f.move_dest_uri; - - String newUri = moveDestUri.value.join("/") - newUri = newUri.replace("//","/") - - String corrected = getCorrectedUri(newUri) - - if (corrected == newUri) { - def node = uriService.findByUri(newUri) - change moveDestUri options { findOptionsBasedOnSelectedNode(node) } - } else { - change moveDestUri value { splitUriPath(corrected) } - } - - - - move_dest_uri_new_node - New node to be added - Enter new node name - - - move_add_node - - <placeholder name="move_add_node">Add</placeholder> - <component> - <name>raised</name> - </component> - <action trigger="set"> - newNodeName: f.move_dest_uri_new_node, - selectedUri: f.move_dest_uri; - - if (newNodeName.value == null || newNodeName.value == "") { - return - } - - String prefixUri = selectedUri.value.join("/") - prefixUri = prefixUri.replace("//","/") - - String newUri = prefixUri + uriService.getUriSeparator() + newNodeName.value - def newNode = uriService.getOrCreate(newUri, com.netgrif.application.engine.petrinet.domain.UriContentType.CASE) - - change selectedUri value { splitUriPath(newNode.uriPath) } - - change newNodeName value { null } - </action> - </data> - <data type="i18n"> - <id>duplicate_new_title</id> - <title name="duplicate_new_title">Title of duplicated view - - - duplicate_view_identifier - View identifier - Must be unique - - - childItemIds - - <allowedNets> - <allowedNet>preference_item</allowedNet> - </allowedNets> - </data> - <data type="taskRef"> - <id>childItemForms</id> - <title/> - </data> - <data type="boolean" immediate="true"> - <id>hasChildren</id> - <title/> - </data> - <data type="button"> - <id>duplicate_reset_childItemIds</id> - <title/> - <action trigger="set"> - hasChildren: f.hasChildren, - childItemIds: f.childItemIds; - - change childItemIds value { [] } - change hasChildren value { false } - </action> - </data> - <data type="text" immediate="true"> - <id>menu_item_identifier</id> - <title name="menu_item_identifier">Menu item identifier - - - nodePath - Item URI - - 0 - - - nodePath: f.nodePath, - menu_item_identifier: f.menu_item_identifier; - - change menu_item_identifier value { - def idx = nodePath.value.lastIndexOf(uriService.getUriSeparator()) - return nodePath.value.substring(idx + 1) - } + ]]> + + + add_allowed_roles + + <placeholder id="allow_roles">Allow view for roles</placeholder> +<!-- todo: release/8.0.0--> +<!-- <event type="set">--> +<!-- <id>add_allowed_roles_set</id>--> +<!-- <actions phase="post">--> +<!-- <action id="action_8">--> +<!-- <![CDATA[--> +<!-- change allowed_roles options {return configurableMenuService.addSelectedRoles(allowed_roles, processes_available, roles_available)}--> +<!-- change roles_available value {[]}--> +<!-- change roles_available options {[:]}--> +<!-- change processes_available value {null}--> +<!-- ]]>--> +<!-- </action>--> +<!-- </actions>--> +<!-- </event>--> + </data> + <data type="button"> + <id>add_banned_roles</id> + <title/> + <placeholder id="ban_roles">Ban view for roles</placeholder> + <!-- todo: release/8.0.0--> +<!-- <event type="set">--> +<!-- <id>add_banned_roles_set</id>--> +<!-- <actions phase="post">--> +<!-- <action id="action_10">--> +<!-- <![CDATA[--> +<!-- change banned_roles options {return configurableMenuService.addSelectedRoles(banned_roles, processes_available, roles_available)}--> +<!-- change roles_available value {[]}--> +<!-- change roles_available options {[:]}--> +<!-- change processes_available value {null}--> +<!-- ]]>--> +<!-- </action>--> +<!-- </actions>--> +<!-- </event>--> + </data> + <data type="enumeration_map"> + <id>additional_filter_autocomplete_selection</id> + <title id="filter_autocomplete_selection">Select new filter + + autocomplete_dynamic + + + additional_filter_autocomplete_selection_set + + + + + + + + additional_filter_autocomplete_selection_get + + + + + + + + + additional_filter_case + + <event type="set"> + <id>additional_filter_case_set</id> + <actions phase="post"> + <action id="action_27"> + <![CDATA[ + if (additional_filter_case.rawValue[0] == null) { + make merge_filters,hidden on task_view_settings when { true } + make filter_header,hidden on task_view_settings when { true } + make remove_additional_filter,hidden on task_view_settings when { true } + change current_additional_filter_preview value { [] } + return + } + def filterCase = findCase(additional_filter_case.rawValue[0]) + change current_additional_filter_preview value { return [filterCase.tasks["view_filter"].getTaskStringId()] } + make merge_filters,editable on task_view_settings when { true } + make filter_header,visible on task_view_settings when { true } + make remove_additional_filter,editable on task_view_settings when { true } + ]]> + </action> + </actions> + </event> + <allowedNets> + <allowedNet>filter</allowedNet> + </allowedNets> + </data> + <data type="enumeration_map" immediate="true"> + <id>allowed_roles</id> + <title id="roles_allowed">Allowed roles + List of roles allowed to view this menu entry. + + + banned_roles + Banned roles + List of roles not allowed to view this menu entry. + + + case_allow_header_table_mode + Allow table mode for headers? + true + + + case_banned_nets_in_creation + Banned processes for creation + Write down process identifiers separated by comma. Example: mynet1,mynet2 + + case_banned_nets_in_creation_set + + + + + + + + + case_default_headers + Set default headers + Example: "meta-title,meta-visualId" + + case_default_headers_set + + + + + + + + + case_headers_default_mode + Default header mode + + + + + + sort + + + case_headers_mode + Header mode + + + + + + sort,edit,search + + case_headers_mode_set + + + + + + + + case_headers_mode_get + + + + + + + + + case_headers_options_holder + + <options> + <option key="sort" id="sort">Sort</option> + <option key="search" id="search">Search</option> + <option key="edit" id="edit">Edit</option> + </options> + </data> + <data type="boolean" immediate="true"> + <id>case_is_header_mode_changeable</id> + <title id="is_header_mode_changeable">Can header mode be changed? + true + + + case_require_title_in_creation + Require title input in case creation? + true + + + case_show_more_menu + Show more menu for case item? + false + + + case_view_header + + <init id="case_view_header">Case view</init> + <component> + <id>divider</id> + </component> + </data> + <data type="enumeration_map" immediate="true"> + <id>case_view_search_type</id> + <title id="case_view_search_type">Search type for case view + + + + + + fulltext_advanced + + + case_view_settings_taskRef + + <init>case_view_settings</init> + </data> + <data type="taskRef"> + <id>childItemForms</id> + <title/> + </data> + <data type="caseRef" immediate="true"> + <id>childItemIds</id> + <title/> + <allowedNets> + <allowedNet>preference_item</allowedNet> + </allowedNets> + </data> + <data type="text" immediate="true"> + <id>create_case_button_icon</id> + <title id="create_case_button_icon">"New case" button icon identifier + add + + create_case_button_icon_set + + + """} + return; + } + change create_case_button_icon_preview value { + """""" + create_case_button_icon.rawValue + """""" + } + ]]> + + + + + + create_case_button_icon_preview + Icon preview + <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"><span class="material-icons">add</span> + + htmltextarea + + + + create_case_button_title + "New case" button title + + + current_additional_filter_preview + + </data> + <data type="taskRef"> + <id>current_filter_preview</id> + <title/> + </data> + <data type="text" immediate="true"> + <id>custom_view_selector</id> + <title id="custom_view_selector">Custom view configuration selector + Example: "demo-tabbed-views" + + + duplicate_new_title + Title of duplicated view + + + duplicate_reset_childItemIds + + <event type="set"> + <id>duplicate_reset_childItemIds_set</id> + <actions phase="post"> + <action id="action_3"> + <![CDATA[ + change childItemIds value { [] } + change hasChildren value { false } + ]]> + </action> + </actions> + </event> + </data> + <data type="text"> + <id>duplicate_view_identifier</id> + <title id="duplicate_view_identifier">View identifier + Must be unique + + + filter_autocomplete_selection + Select new filter + + autocomplete_dynamic + + + filter_autocomplete_selection_set + + + + + + + + filter_autocomplete_selection_get + + + + + + + + + filter_case + + <event type="set"> + <id>filter_case_set</id> + <actions phase="post"> + <action id="action_17"> + <![CDATA[ + if (filter_case.rawValue == null || filter_case.rawValue == []) { + return + } + def filterCase = findCase(filter_case.rawValue[0]) + change current_filter_preview value {return [filterCase.tasks["view_filter"].getTaskStringId()]} + if (filterCase.dataSet["filter_type"].rawValue == "Case") { + make case_view_header,editable on item_settings when { true } + make case_view_settings_taskRef,editable on item_settings when { true } + make additional_filter_autocomplete_selection,editable on task_view_settings when { true } + make update_additional_filter,visible on task_view_settings when { true } + make selected_additional_filter_preview,visible on task_view_settings when { true } + make merge_filters,visible on task_view_settings when { true } + make filter_header,visible on task_view_settings when { true } + make current_additional_filter_preview,visible on task_view_settings when { true } + } else { + make case_view_header,hidden on item_settings when { true } + make case_view_settings_taskRef,hidden on item_settings when { true } + make additional_filter_autocomplete_selection,hidden on task_view_settings when { true } + make update_additional_filter,hidden on task_view_settings when { true } + make selected_additional_filter_preview,hidden on task_view_settings when { true } + make merge_filters,hidden on task_view_settings when { true } + make filter_header,hidden on task_view_settings when { true } + make current_additional_filter_preview,hidden on task_view_settings when { true } + } + make task_view_header,editable on item_settings when { true } + make task_view_settings_taskRef,editable on item_settings when { true } + change additional_filter_case value { [] } + ]]> + </action> + </actions> + </event> + <allowedNets> + <allowedNet>filter</allowedNet> + </allowedNets> + </data> + <data type="i18n"> + <id>filter_header</id> + <title/> + <init id="filter_header">Current filter</init> + <component> + <id>divider</id> + </component> + </data> + <data type="boolean" immediate="true"> + <id>hasChildren</id> + <title/> + </data> + <data type="text" immediate="true"> + <id>menu_icon</id> + <title id="icon_identifier">Menu icon identifier + Material icon identifier. List of icons with identifiers is available online. + + menu_icon_set + + + """} + return; + } + change menu_icon_preview value { + """""" + menu_icon.rawValue + """""" + } + ]]> + + + + + + menu_icon_preview + Menu icon preview + + htmltextarea + + + + menu_item_identifier + Menu item identifier + + + menu_name + Name of the item + Will be shown in the menu + + menu_name_set + + + + + + + + + menu_name_as_visible + Name of the item + Is shown in the menu + + autocomplete + + + + merge_filters + Merge with base filter? + true + + + move_add_node + + <placeholder id="move_add_node">Add</placeholder> + <component> + <id>raised</id> + </component> + <event type="set"> + <id>move_add_node_set</id> + <actions phase="post"> + <action id="action_2"> + <![CDATA[ + if (move_dest_uri_new_node.rawValue == null || move_dest_uri_new_node.rawValue == "") { + return + } + String prefixUri = move_dest_uri.rawValue.join("/") + prefixUri = prefixUri.replace("//","/") + String newUri = prefixUri + uriService.getUriSeparator() + move_dest_uri_new_node.rawValue + def newNode = uriService.getOrCreate(newUri, com.netgrif.application.engine.petrinet.domain.UriContentType.CASE) + change move_dest_uri value { splitUriPath(newNode.uriPath) } + change move_dest_uri_new_node value { null } + ]]> + </action> + </actions> + </event> + </data> + <data type="multichoice_map"> + <id>move_dest_uri</id> + <title id="move_dest_uri">Destination URI + List of nodes representing destination URI + + autocomplete + + + move_dest_uri_get + + + + + + + + move_dest_uri_set + + + + + + + + + move_dest_uri_new_node + New node to be added + Enter new node name + + + move_previous_dest_uri + + </data> + <data type="text"> + <id>new_filter_id</id> + <title/> + </data> + <data type="text" immediate="true"> + <id>nodePath</id> + <title id="nodePath">Item URI + + nodePath_set + + + + + + + + + order_down + + <placeholder>south</placeholder> + <component> + <id>icon</id> + <properties> + <property key="stretch">true</property> + </properties> + </component> + <event type="set"> + <id>order_down_set</id> + <actions phase="post"> + <action id="action_31"> + <![CDATA[ + def parentCase = workflowService.findOne(parentId.rawValue[0]) + def taskId = useCase.tasks.find { it.transition == "row_for_ordering" }.task + def taskRefValue = parentCase.dataSet['childItemForms'].rawValue + int taskRefValueSize = taskRefValue.size() + def caseRefValue = parentCase.dataSet['childItemIds'].rawValue + int caseRefValueSize = caseRefValue.size() + int idxInTaskRef = taskRefValue.indexOf(taskId) + if (idxInTaskRef < taskRefValueSize - 1) { + Collections.swap(taskRefValue, idxInTaskRef, idxInTaskRef + 1) + } + int idxInCaseRef = caseRefValue.indexOf(useCase.stringId) + if (idxInCaseRef < caseRefValueSize - 1) { + Collections.swap(caseRefValue, idxInCaseRef, idxInCaseRef + 1) + } + setData("children_order", parentCase, [ + "childItemForms" : [ + "value" : taskRefValue, + "type" : "taskRef" + ], + "childItemIds" : [ + "value" : caseRefValue, + "type" : "caseRef" + ] + ]) + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>order_up</id> + <title/> + <placeholder>north</placeholder> + <component> + <id>icon</id> + <properties> + <property key="stretch">true</property> + </properties> + </component> + <event type="set"> + <id>order_up_set</id> + <actions phase="post"> + <action id="action_32"> + <![CDATA[ + def parentCase = workflowService.findOne(parentId.rawValue[0]) + def taskId = useCase.tasks.find { it.transition == "row_for_ordering" }.task + def taskRefValue = parentCase.dataSet['childItemForms'].rawValue + def caseRefValue = parentCase.dataSet['childItemIds'].rawValue + int idxInTaskRef = taskRefValue.indexOf(taskId) + if (idxInTaskRef > 0) { + Collections.swap(taskRefValue, idxInTaskRef - 1, idxInTaskRef) + } else { + return + } + int idxInCaseRef = caseRefValue.indexOf(useCase.stringId) + if (idxInCaseRef > 0) { + Collections.swap(caseRefValue, idxInCaseRef - 1, idxInCaseRef) + } else { + return + } + setData("children_order", parentCase, [ + "childItemForms" : [ + "value" : taskRefValue, + "type" : "taskRef" + ], + "childItemIds" : [ + "value" : caseRefValue, + "type" : "caseRef" + ] + ]) + ]]> + </action> + </actions> + </event> + </data> + <data type="caseRef"> + <id>parentId</id> + <title/> + <allowedNets> + <allowedNet>preference_item</allowedNet> + </allowedNets> + </data> + <data type="enumeration_map" immediate="true"> + <id>processes_available</id> + <title id="available_processes">Your processes + Select a process containing roles you wish to add to allowed or banned roles lists. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + remove_additional_filter + + <placeholder id="remove_additional_filter">Remove additional filter</placeholder> + <component> + <id>raised</id> + </component> + <event type="set"> + <id>remove_additional_filter_set</id> + <actions phase="post"> + <action id="action_26"> + <![CDATA[ + change additional_filter_case value { [] } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>remove_allowed_roles</id> + <title/> + <placeholder id="remove_from_allowed_roles">Remove from allowed roles</placeholder> + <!-- todo: release/8.0.0--> +<!-- <event type="set">--> +<!-- <id>remove_allowed_roles_set</id>--> +<!-- <actions phase="post">--> +<!-- <action id="action_9">--> +<!-- <![CDATA[--> +<!-- change allowed_roles options {return configurableMenuService.removeSelectedRoles(allowed_roles)}--> +<!-- change allowed_roles value {[]}--> +<!-- change roles_available value {[]}--> +<!-- change roles_available options {[:]}--> +<!-- change processes_available value {null}--> +<!-- ]]>--> +<!-- </action>--> +<!-- </actions>--> +<!-- </event>--> + </data> + <data type="button"> + <id>remove_banned_roles</id> + <title/> + <placeholder id="remove_from_banned_roles">Remove from banned roles</placeholder> + <!-- todo: release/8.0.0--> +<!-- <event type="set">--> +<!-- <id>remove_banned_roles_set</id>--> +<!-- <actions phase="post">--> +<!-- <action id="action_11">--> +<!-- <![CDATA[--> +<!-- change banned_roles options { return configurableMenuService.removeSelectedRoles(banned_roles) }--> +<!-- change banned_roles value { [] }--> +<!-- change roles_available value { [] }--> +<!-- change roles_available options { [:] }--> +<!-- change processes_available value { null }--> +<!-- ]]>--> +<!-- </action>--> +<!-- </actions>--> +<!-- </event>--> + </data> + <data type="multichoice_map" immediate="true"> + <id>roles_available</id> + <title id="available_roles">Available roles from selected process + + + selected_additional_filter_preview + + </data> + <data type="taskRef"> + <id>selected_filter_preview</id> + <title/> + </data> + <data type="boolean" immediate="true"> + <id>show_create_case_button</id> + <title id="show_create_case_button">Show create case button? + true + + + tab_icon + Tab icon identifier + Material icon identifier. List of icons with identifiers is available online. + + tab_icon_set + + + """} + return; + } + change tab_icon_preview value { + """""" + tab_icon.rawValue + """""" + } + ]]> + + + + + + tab_icon_preview + Tab icon preview + + htmltextarea + + + + tab_name + Name of the item + Will be shown in tab + + + task_allow_header_table_mode + Allow table mode for headers? + true + + + task_default_headers + Set default headers + Example: "meta-title,meta-user" + + task_default_headers_set + + + + + + + + + task_headers_default_mode + Default header mode + + + + + sort + + + task_headers_mode + Header mode + + + + + sort,edit + + task_headers_mode_set + + + + + + + + task_headers_mode_get + + + + + + + + + task_headers_options_holder + + <options> + <option key="sort" id="sort">Sort</option> + <option key="edit" id="edit">Edit</option> + </options> + </data> + <data type="boolean" immediate="true"> + <id>task_is_header_mode_changeable</id> + <title id="is_header_mode_changeable">Can header mode be changed? + true + + + task_show_more_menu + Show more menu for task item? + true + + + task_view_header + + <init id="task_view_header">Task view</init> + <component> + <id>divider</id> + </component> + </data> + <data type="enumeration_map" immediate="true"> + <id>task_view_search_type</id> + <title id="task_view_search_type">Search type for task view + + + + + + fulltext_advanced + + + task_view_settings_taskRef + + <init>task_view_settings</init> + </data> + <data type="button"> + <id>update_additional_filter</id> + <title/> + <placeholder id="update_filter">Update view with selected filter</placeholder> + <component> + <id>raised</id> + </component> + <event type="set"> + <id>update_additional_filter_set</id> + <actions phase="post"> + <action id="action_25"> + <![CDATA[ + change additional_filter_case value { [additional_filter_autocomplete_selection.rawValue] } + change additional_filter_autocomplete_selection value { "" } + make update_additional_filter,visible on task_view_settings when { true } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>update_filter</id> + <title/> + <placeholder id="update_filter">Update view with selected filter</placeholder> + <component> + <id>raised</id> + </component> + <event type="set"> + <id>update_filter_set</id> + <actions phase="post"> + <action id="action_16"> + <![CDATA[ + change filter_case value { [filter_autocomplete_selection.rawValue] } + change filter_autocomplete_selection value { "" } + make update_filter,visible on item_settings when { true } + ]]> </action> - </actions> - </event> - </data> - - <!-- GENERAL CONFIGURATION DATA --> - <data type="text" immediate="true"> - <id>menu_icon</id> - <title name="icon_identifier">Menu icon identifier - Material icon identifier. List of icons with identifiers is available online. - - icon: f.this, - iconPreview: f.menu_icon_preview; - - changeCaseProperty "icon" about { icon.value; } - - if (icon.value == "") { - change iconPreview value {"""]]>} - return; - } - - change iconPreview value { - """]]> + icon.value + """]]> - } - - - - menu_icon_preview - Menu icon preview - - htmltextarea - - - - menu_name_as_visible - Name of the item - Is shown in the menu - - autocomplete - - - - menu_name - Name of the item - Will be shown in the menu - - menu_name_as_visible: f.menu_name_as_visible, - name: f.menu_name; - - changeCaseProperty "title" about { name.value } - change menu_name_as_visible choices { [name.value] } - change menu_name_as_visible value { name.value } - - - - tab_icon - Tab icon identifier - Material icon identifier. List of icons with identifiers is available online. - - icon: f.this, - iconPreview: f.tab_icon_preview; - - if (icon.value == "") { - change iconPreview value {"""]]>} - return; - } - - change iconPreview value { - """]]> + icon.value + """]]> - } - - - - tab_icon_preview - Tab icon preview - - htmltextarea - - - - use_tab_icon - Display tab icon? - true - - - tab_name - Name of the item - Will be shown in tab - - - add_allowed_roles - - <placeholder name="allow_roles">Allow view for roles</placeholder> - <action trigger="set"> - allowedRoles: f.allowed_roles, - processesAvailable: f.processes_available, - rolesAvailable: f.roles_available; - - change allowedRoles options {return configurableMenuService.addSelectedRoles(allowedRoles, processesAvailable, rolesAvailable)} - - change rolesAvailable value {[]} - change rolesAvailable options {[:]} - change processesAvailable value {null} - </action> - </data> - <data type="button"> - <id>remove_allowed_roles</id> - <title/> - <placeholder name="remove_from_allowed_roles">Remove from allowed roles</placeholder> - <action trigger="set"> - allowedRoles: f.allowed_roles, - processesAvailable: f.processes_available, - rolesAvailable: f.roles_available; - - change allowedRoles options {return configurableMenuService.removeSelectedRoles(allowedRoles)} - - change allowedRoles value {[]} - change rolesAvailable value {[]} - change rolesAvailable options {[:]} - change processesAvailable value {null} - </action> - </data> - <data type="button"> - <id>add_banned_roles</id> - <title/> - <placeholder name="ban_roles">Ban view for roles</placeholder> - <action trigger="set"> - bannedRoles: f.banned_roles, - processesAvailable: f.processes_available, - rolesAvailable: f.roles_available; - - change bannedRoles options {return configurableMenuService.addSelectedRoles(bannedRoles, processesAvailable, rolesAvailable)} - - change rolesAvailable value {[]} - change rolesAvailable options {[:]} - change processesAvailable value {null} - </action> - </data> - <data type="button"> - <id>remove_banned_roles</id> - <title/> - <placeholder name="remove_from_banned_roles">Remove from banned roles</placeholder> - <action trigger="set"> - bannedRoles: f.banned_roles, - processesAvailable: f.processes_available, - rolesAvailable: f.roles_available; - - change bannedRoles options { return configurableMenuService.removeSelectedRoles(bannedRoles) } - - change bannedRoles value { [] } - change rolesAvailable value { [] } - change rolesAvailable options { [:] } - change processesAvailable value { null } - </action> - </data> - <data type="enumeration_map" immediate="true"> - <id>processes_available</id> - <title name="available_processes">Your processes - Select a process containing roles you wish to add to allowed or banned roles lists. - - processes: f.this; - - change processes options { return configurableMenuService.getNetsByAuthorAsMapOptions(loggedUser(), org.springframework.context.i18n.LocaleContextHolder.locale) } - - - processes: f.this, - allowedRoles: f.allowed_roles, - bannedRoles: f.banned_roles, - rolesAvailable: f.roles_available; - - if (processes.value != null) { - change rolesAvailable options { return configurableMenuService.getAvailableRolesFromNet(processes, allowedRoles, bannedRoles) } - } else { - change rolesAvailable options { [:] } - } - change rolesAvailable value { [] } - - - - roles_available - Available roles from selected process - - - allowed_roles - Allowed roles - List of roles allowed to view this menu entry. - - [:] - - - - banned_roles - Banned roles - List of roles not allowed to view this menu entry. - - [:] - - - - selected_filter_preview - - </data> - <data type="taskRef"> - <id>current_filter_preview</id> - <title/> - </data> - <data type="i18n"> - <id>filter_header</id> - <title/> - <init name="filter_header">Current filter</init> - <component> - <name>divider</name> - </component> - </data> - <data type="text"> - <id>new_filter_id</id> - <title/> - </data> - <data type="enumeration_map"> - <id>filter_autocomplete_selection</id> - <title name="filter_autocomplete_selection">Select new filter - - autocomplete_dynamic - - - trans: t.item_settings, - useCustomView: f.use_custom_view, - filterAutocomplete: f.this, - filter_case: f.filter_case, - update_filter: f.update_filter, - previewTaskRef: f.selected_filter_preview; - - updateFilterAutocompleteOptions(filterAutocomplete, previewTaskRef, filter_case, update_filter, trans, false) - - make update_filter,hidden on trans when { useCustomView.value } - - - trans: t.item_settings, - useCustomView: f.use_custom_view, - filterAutocomplete: f.this, - filter_case: f.filter_case, - update_filter: f.update_filter, - previewTaskRef: f.selected_filter_preview; - - updateFilterAutocompleteOptions(filterAutocomplete, previewTaskRef, filter_case, update_filter, trans, false) - - make update_filter,hidden on trans when { useCustomView.value } - - - - update_filter - - <placeholder name="update_filter">Update view with selected filter</placeholder> - <component> - <name>raised</name> - </component> - <action trigger="set"> - trans: t.item_settings, - update_filter: f.update_filter, - filter_case: f.filter_case, - filterAutocomplete: f.filter_autocomplete_selection; - - change filter_case value { [filterAutocomplete.value] } - change filterAutocomplete value { "" } - make update_filter,visible on trans when { true } - </action> - </data> - <data type="caseRef"> - <id>filter_case</id> - <title/> - <action trigger="set"> - additionalFilterCase: f.additional_filter_case, - additionalAutocomplete: f.additional_filter_autocomplete_selection, - additionalUpdate: f.update_additional_filter, - additionalFilterPreview: f.selected_additional_filter_preview, - mergeFilters: f.merge_filters, - filterHeader: f.filter_header, - currentAdditionalFilterPreview: f.current_additional_filter_preview, - taskSettingsTrans: t.task_view_settings, - settingsTrans: t.item_settings, - caseViewHeader: f.case_view_header, - caseViewSettingsTaskRef: f.case_view_settings_taskRef, - taskViewHeader: f.task_view_header, - taskViewSettingsTaskRef: f.task_view_settings_taskRef, - filterTaskRef: f.current_filter_preview, - filterCaseRef: f.filter_case; - - if (filterCaseRef.value == null || filterCaseRef.value == []) { - return - } - - def filterCase = findCase(filterCaseRef.rawValue[0]) - change filterTaskRef value {return [filterCase.tasks["view_filter"].getTaskStringId()]} - - if (filterCase.dataSet["filter_type"].value == "Case") { - make caseViewHeader,editable on settingsTrans when { true } - make caseViewSettingsTaskRef,editable on settingsTrans when { true } - - make additionalAutocomplete,editable on taskSettingsTrans when { true } - make additionalUpdate,visible on taskSettingsTrans when { true } - make additionalFilterPreview,visible on taskSettingsTrans when { true } - make mergeFilters,visible on taskSettingsTrans when { true } - make filterHeader,visible on taskSettingsTrans when { true } - make currentAdditionalFilterPreview,visible on taskSettingsTrans when { true } - } else { - make caseViewHeader,hidden on settingsTrans when { true } - make caseViewSettingsTaskRef,hidden on settingsTrans when { true } - - make additionalAutocomplete,hidden on taskSettingsTrans when { true } - make additionalUpdate,hidden on taskSettingsTrans when { true } - make additionalFilterPreview,hidden on taskSettingsTrans when { true } - make mergeFilters,hidden on taskSettingsTrans when { true } - make filterHeader,hidden on taskSettingsTrans when { true } - make currentAdditionalFilterPreview,hidden on taskSettingsTrans when { true } - } - make taskViewHeader,editable on settingsTrans when { true } - make taskViewSettingsTaskRef,editable on settingsTrans when { true } - - change additionalFilterCase value { [] } - </action> - <allowedNets> - <allowedNet>filter</allowedNet> - </allowedNets> - </data> - <data type="boolean" immediate="true"> - <id>use_custom_view</id> - <title name="use_custom_view">Use custom view? - false - - - custom_view_selector - Custom view configuration selector - Example: "demo-tabbed-views" - - - - - case_view_search_type - Search type for case view - - - - - - fulltext_advanced - - - create_case_button_title - "New case" button title - - - create_case_button_icon_preview - Icon preview - add]]> - - htmltextarea - - - - create_case_button_icon - "New case" button icon identifier - add - - create_case_button_icon_preview: f.create_case_button_icon_preview, - create_case_button_icon: f.create_case_button_icon; - - - if (create_case_button_icon.value == "") { - change create_case_button_icon_preview value {"""]]>} - return; - } - - change create_case_button_icon_preview value { - """]]> + create_case_button_icon.value + """]]> - } - - - - show_create_case_button - Show create case button? - true - - - case_require_title_in_creation - Require title input in case creation? - true - - - case_banned_nets_in_creation - Banned processes for creation - Write down process identifiers separated by comma. Example: mynet1,mynet2 - - bannedNets: f.this; - - String trimmed = bannedNets.value?.replaceAll("\\s","") - if (bannedNets.value != trimmed) { - change bannedNets value { trimmed } - } - - - - case_view_header - - <init name="case_view_header">Case view</init> - <component> - <name>divider</name> - </component> - </data> - <data type="taskRef"> - <id>case_view_settings_taskRef</id> - <title/> - <init>case_view_settings</init> - </data> - <data type="boolean" immediate="true"> - <id>case_show_more_menu</id> - <title name="case_show_more_menu">Show more menu for case item? - false - - - case_allow_header_table_mode - Allow table mode for headers? - true - - - case_headers_mode - Header mode - - - - - - sort,edit,search - - headersMode: f.case_headers_mode, - defaultMode: f.case_headers_default_mode, - holder: f.case_headers_options_holder; - - updateOptionsBasedOnValue(defaultMode, headersMode, holder) - - - headersMode: f.case_headers_mode, - defaultMode: f.case_headers_default_mode, - holder: f.case_headers_options_holder; - - updateOptionsBasedOnValue(defaultMode, headersMode, holder) - - - - case_headers_default_mode - Default header mode - - - - - - sort - - - case_headers_options_holder - - <options> - <option key="sort" name="sort">Sort</option> - <option key="search" name="search">Search</option> - <option key="edit" name="edit">Edit</option> - </options> - </data> - <data type="boolean" immediate="true"> - <id>case_is_header_mode_changeable</id> - <title name="is_header_mode_changeable">Can header mode be changed? - true - - - use_case_default_headers - Use custom default headers? - true - - - case_default_headers - Set default headers - Example: "meta-title,meta-visualId" - - defaultHeaders: f.this; - - String trimmed = defaultHeaders.value?.replaceAll("\\s","") - if (defaultHeaders.value != trimmed) { - change defaultHeaders value { trimmed } - } - - - - - - selected_additional_filter_preview - - </data> - <data type="taskRef"> - <id>current_additional_filter_preview</id> - <title/> - </data> - <data type="enumeration_map"> - <id>additional_filter_autocomplete_selection</id> - <title name="filter_autocomplete_selection">Select new filter - - autocomplete_dynamic - - - trans: t.task_view_settings, - filterAutocomplete: f.this, - filterCase: f.additional_filter_case, - updateFilter: f.update_additional_filter, - previewTaskRef: f.selected_additional_filter_preview; - - updateFilterAutocompleteOptions(filterAutocomplete, previewTaskRef, filterCase, updateFilter, trans, true) - - - trans: t.task_view_settings, - filterAutocomplete: f.this, - filterCase: f.additional_filter_case, - updateFilter: f.update_additional_filter, - previewTaskRef: f.selected_additional_filter_preview; - - updateFilterAutocompleteOptions(filterAutocomplete, previewTaskRef, filterCase, updateFilter, trans, true) - - - - update_additional_filter - - <placeholder name="update_filter">Update view with selected filter</placeholder> - <component> - <name>raised</name> - </component> - <action trigger="set"> - trans: t.task_view_settings, - updateFilter: f.update_additional_filter, - filterCase: f.additional_filter_case, - filterAutocomplete: f.additional_filter_autocomplete_selection; - - change filterCase value { [filterAutocomplete.rawValue] } - change filterAutocomplete value { "" } - make updateFilter,visible on trans when { true } - </action> - </data> - <data type="button"> - <id>remove_additional_filter</id> - <title/> - <placeholder name="remove_additional_filter">Remove additional filter</placeholder> - <component> - <name>raised</name> - </component> - <action trigger="set"> - filterCase: f.additional_filter_case; - - change filterCase value { [] } - </action> - </data> - <data type="caseRef"> - <id>additional_filter_case</id> - <title/> - <action trigger="set"> - taskViewTrans: t.task_view_settings, - mergeFilters: f.merge_filters, - filterHeader: f.filter_header, - filterTaskRef: f.current_additional_filter_preview, - removeButton: f.remove_additional_filter, - filterCaseRef: f.additional_filter_case; - - if (filterCaseRef.rawValue[0] == null) { - make mergeFilters,hidden on taskViewTrans when { true } - make filterHeader,hidden on taskViewTrans when { true } - make removeButton,hidden on taskViewTrans when { true } - change filterTaskRef value { [] } - return - } - - def filterCase = findCase(filterCaseRef.rawValue[0]) - change filterTaskRef value { return [filterCase.tasks["view_filter"].getTaskStringId()] } - make mergeFilters,editable on taskViewTrans when { true } - make filterHeader,visible on taskViewTrans when { true } - make removeButton,editable on taskViewTrans when { true } - </action> - <allowedNets> - <allowedNet>filter</allowedNet> - </allowedNets> - </data> - <data type="boolean" immediate="true"> - <id>merge_filters</id> - <title name="merge_filters">Merge with base filter? - true - - - task_view_settings_taskRef - - <init>task_view_settings</init> - </data> - <data type="i18n"> - <id>task_view_header</id> - <title/> - <init name="task_view_header">Task view</init> - <component> - <name>divider</name> - </component> - </data> - <data type="enumeration_map" immediate="true"> - <id>task_view_search_type</id> - <title name="task_view_search_type">Search type for task view - - - - - - fulltext_advanced - - - task_headers_mode - Header mode - - - - - sort,edit - - headersMode: f.task_headers_mode, - defaultMode: f.task_headers_default_mode, - holder: f.task_headers_options_holder; - - updateOptionsBasedOnValue(defaultMode, headersMode, holder) - - - headersMode: f.case_headers_mode, - defaultMode: f.case_headers_default_mode, - holder: f.case_headers_options_holder; - - updateOptionsBasedOnValue(defaultMode, headersMode, holder) - - - - task_headers_default_mode - Default header mode - - - - - sort - - - task_headers_options_holder - - <options> - <option key="sort" name="sort">Sort</option> - <option key="edit" name="edit">Edit</option> - </options> - </data> - <data type="boolean" immediate="true"> - <id>task_is_header_mode_changeable</id> - <title name="is_header_mode_changeable">Can header mode be changed? - true - - - task_allow_header_table_mode - Allow table mode for headers? - true - - - use_task_default_headers - Use custom default headers? - true - - - task_default_headers - Set default headers - Example: "meta-title,meta-user" - - defaultHeaders: f.this; - - String trimmed = defaultHeaders.value?.replaceAll("\\s","") - if (defaultHeaders.value != trimmed) { - change defaultHeaders value { trimmed } - } - - - - task_show_more_menu - Show more menu for task item? - true - - - order_down - - <placeholder>south</placeholder> - <component> - <name>icon</name> - <property key="stretch">true</property> - </component> - <action trigger="set"> - parentId: f.parentId; - - def parentCase = workflowService.findOne(parentId.value[0]) - def taskId = useCase.tasks.find { it.transition == "row_for_ordering" }.task - def taskRefValue = parentCase.dataSet['childItemForms'].value - int taskRefValueSize = taskRefValue.size() - def caseRefValue = parentCase.dataSet['childItemIds'].value - int caseRefValueSize = caseRefValue.size() - - int idxInTaskRef = taskRefValue.indexOf(taskId) - if (idxInTaskRef < taskRefValueSize - 1) { - Collections.swap(taskRefValue, idxInTaskRef, idxInTaskRef + 1) - } - - int idxInCaseRef = caseRefValue.indexOf(useCase.stringId) - if (idxInCaseRef < caseRefValueSize - 1) { - Collections.swap(caseRefValue, idxInCaseRef, idxInCaseRef + 1) - } - - setData("children_order", parentCase, [ - "childItemForms" : [ - "value" : taskRefValue, - "type" : "taskRef" - ], - "childItemIds" : [ - "value" : caseRefValue, - "type" : "caseRef" - ] - ]) - </action> - </data> - <data type="button"> - <id>order_up</id> - <title/> - <placeholder>north</placeholder> - <component> - <name>icon</name> - <property key="stretch">true</property> - </component> - <action trigger="set"> - parentId: f.parentId; - - def parentCase = workflowService.findOne(parentId.value[0]) - def taskId = useCase.tasks.find { it.transition == "row_for_ordering" }.task - def taskRefValue = parentCase.dataSet['childItemForms'].value - def caseRefValue = parentCase.dataSet['childItemIds'].value - - int idxInTaskRef = taskRefValue.indexOf(taskId) - if (idxInTaskRef > 0) { - Collections.swap(taskRefValue, idxInTaskRef - 1, idxInTaskRef) - } else { - return - } - - int idxInCaseRef = caseRefValue.indexOf(useCase.stringId) - if (idxInCaseRef > 0) { - Collections.swap(caseRefValue, idxInCaseRef - 1, idxInCaseRef) - } else { - return - } - - setData("children_order", parentCase, [ - "childItemForms" : [ - "value" : taskRefValue, - "type" : "taskRef" - ], - "childItemIds" : [ - "value" : caseRefValue, - "type" : "caseRef" - ] - ]) - </action> - </data> - - <!-- I18NS --> - <i18n locale="sk"> - <i18nString name="icon_preview">Náhľad ikony</i18nString> - <i18nString name="icon_identifier">Identifikátor ikony</i18nString> - <i18nString name="icon_identifier_desc">Identifikátor Material ikony. Zoznam ikon s identifikátormi je dostupný online.</i18nString> - <i18nString name="allow_roles">Pridaj k povoleným roliam</i18nString> - <i18nString name="remove_from_allowed_roles">Odstráň z povolených rolí</i18nString> - <i18nString name="ban_roles">Pridaj k zakázaným roliam</i18nString> - <i18nString name="remove_from_banned_roles">Odstráň zo zakázaných rolí</i18nString> - <i18nString name="available_processes">Vaše procesy</i18nString> - <i18nString name="available_processes_desc">Vyberte proces obsahujúci roly ktoré chcete pridať do zoznamu povolených alebo zakázaných rolí.</i18nString> - <i18nString name="available_roles">Dostupné roly</i18nString> - <i18nString name="create_case_button_title">Názov tlačidla "Nová inštancia"</i18nString> - <i18nString name="create_case_button_icon">Identifikátor ikony tlačidla "Nová inštancia"</i18nString> - <i18nString name="create_case_button_icon_preview">Náhľad ikony</i18nString> - <i18nString name="default_headers">Predvolené hlavičky</i18nString> - <i18nString name="default_headers_desc">Napríklad: "meta-title,meta-visualId"</i18nString> - <i18nString name="filter_autocomplete_selection">Zvoľte nový filter</i18nString> - <i18nString name="move_dest_uri">Cieľové URI</i18nString> - <i18nString name="duplicate_new_title">Názov duplikovanej položky</i18nString> - <i18nString name="duplicate_view_identifier">Identifikátor duplikovanej položky</i18nString> - <i18nString name="duplicate_view_identifier_desc">Musí byť jedinečný</i18nString> - <i18nString name="name">Názov položky</i18nString> - <i18nString name="name_desc">Bude zobrazený v menu</i18nString> - <i18nString name="tab_icon">Identifikátor ikony v karte</i18nString> - <i18nString name="tab_icon_identifier_desc">Identifikátor Material ikony. Zoznam ikon s identifikátormi je dostupný online.</i18nString> - <i18nString name="display_tab_icon">Zobraziť ikonu v karte?</i18nString> - <i18nString name="tab_name">Názov položky</i18nString> - <i18nString name="tab_name_desc">Bude zobrazený v karte</i18nString> - <i18nString name="update_filter">Aktualizovať zobrazenie s vybraným filtrom</i18nString> - <i18nString name="use_custom_view">Použiť vlastné zobrazenie?</i18nString> - <i18nString name="custom_view_selector">Konfiguračný identifikátor vlastného zobrazenia</i18nString> - <i18nString name="custom_view_selector_desc">Napríklad: "demo-tabbed-views"</i18nString> - <i18nString name="case_view_search_type">Typ vyhľadávania prípadov</i18nString> - <i18nString name="hidden">Skryté</i18nString> - <i18nString name="fulltext">Fulltext</i18nString> - <i18nString name="fulltext_advanced">Fulltext a rozšírené</i18nString> - <i18nString name="case_require_title_in_creation">Vyžadovať názov inštancii pri vytváraní?</i18nString> - <i18nString name="case_banned_nets_in_creation">Zakázané siete pri vytváraní</i18nString> - <i18nString name="case_banned_nets_in_creation_desc">Uveďte identifikátory procesov oddelené čiarkou. Napríklad: mynet1,mynet2</i18nString> - <i18nString name="show_create_case_button">Zobraziť tlačidlo na vytvorenie prípadu?</i18nString> - <i18nString name="case_show_more_menu">Zobrazovať menu pre prípadovú položku?</i18nString> - <i18nString name="sort">Zoraďovanie</i18nString> - <i18nString name="search">Vyhľadávanie</i18nString> - <i18nString name="edit">Upravovanie</i18nString> - <i18nString name="merge_filters">Zjednotiť filter so základným filtrom?</i18nString> - <i18nString name="task_view_search_type">Typ vyhľadávania úloh</i18nString> - <i18nString name="headers_mode">Mód hlavičiek</i18nString> - <i18nString name="headers_default_mode">Predvolený mód hlavičiek</i18nString> - <i18nString name="is_header_mode_changeable">Môže byť mód hlavičiek zmenený?</i18nString> - <i18nString name="allow_header_table_mode">Povoliť tabuľkový mód pre hlavičky?</i18nString> - <i18nString name="use_default_headers">Použiť vlastné predvolené hlavičky?</i18nString> - <i18nString name="task_default_headers">Predvolené hlavičky</i18nString> - <i18nString name="task_default_headers_desc">Napríklad: "meta-title,meta-user"</i18nString> - <i18nString name="task_show_more_menu">Zobrazovať menu pre úlohovú položku?</i18nString> - <i18nString name="item_settings">Nastavenie položky</i18nString> - <i18nString name="roles_management_title">Roly</i18nString> - <i18nString name="filter_update_title">Filter</i18nString> - <i18nString name="move_item">Presunúť položku</i18nString> - <i18nString name="move_item_finish">Presunúť</i18nString> - <i18nString name="duplicate_item">Duplikovať položku</i18nString> - <i18nString name="duplicate_item_finish">Duplikovať</i18nString> - <i18nString name="additional_filter_update">Dodatočný filter</i18nString> - <i18nString name="filter_header">Súčasný filter</i18nString> - <i18nString name="case_view_header">Zobrazenie prípadov</i18nString> - <i18nString name="task_view_header">Zobrazenie úloh</i18nString> - <i18nString name="roles_allowed">Povolené roly</i18nString> - <i18nString name="roles_allowed_desc">Zoznam povolených rolí, ktoré môžu zobraziť túto položku</i18nString> - <i18nString name="roles_banned">Zakázané roly</i18nString> - <i18nString name="roles_banned_desc">Zoznam zakázaných rolí, ktoré nemôžu zobraziť túto položku</i18nString> - <i18nString name="item_settings_general">Všeobecné</i18nString> - <i18nString name="menu_item_identifier">Identifikátor položky</i18nString> - <i18nString name="remove_additional_filter">Odstrániť dodatočný filter</i18nString> - <i18nString name="nodePath">URI položky</i18nString> - <i18nString name="move_dest_uri_new_node">Nový uzol</i18nString> - <i18nString name="move_dest_uri_new_node_desc">Uveďte názov uzlu, ktorý chcete pridať</i18nString> - <i18nString name="move_dest_uri_desc">Zoznam uzlov reprezentujúce cieľovú URI</i18nString> - <i18nString name="move_add_node">Pridať</i18nString> - </i18n> - <i18n locale="de"> - <i18nString name="icon_preview">Ikonevorschau</i18nString> - <i18nString name="icon_identifier">Ikone ID</i18nString> - <i18nString name="icon_identifier_desc">Material Ikone ID. Liste den Ikonen mit IDs ist online verfügbar.</i18nString> - <i18nString name="allow_roles">Zu zulässigen Rollen hinzufügen</i18nString> - <i18nString name="remove_from_allowed_roles">Aus zulässigen Rollen entfernen</i18nString> - <i18nString name="ban_roles">Zu verbotenen Rollen hinzufügen</i18nString> - <i18nString name="remove_from_banned_roles">Aus verbotenen Rollen entfernen</i18nString> - <i18nString name="available_processes">Ihre Prozesse</i18nString> - <i18nString name="available_processes_desc">Wählen Sie einen Prozess mit Rollen aus, die Sie zu Listen mit zulässigen oder verbotenen Rollen hinzufügen möchten.</i18nString> - <i18nString name="available_roles">Verfügbare Rollen</i18nString> - <i18nString name="create_case_button_title">Schaltflächentitel "Neuer Fall"</i18nString> - <i18nString name="create_case_button_icon">Ikone ID</i18nString> - <i18nString name="create_case_button_icon_preview">Ikonevorschau</i18nString> - <i18nString name="default_headers">Anzuzeigende Attributmenge auswählen</i18nString> - <i18nString name="filter_autocomplete_selection">Neue Filter auswählen</i18nString> - <i18nString name="default_headers_desc">Beispiel: "meta-title,meta-visualId"</i18nString> - <i18nString name="tab_icon_identifier_desc">Material Ikone ID. Liste den Ikonen mit IDs ist online verfügbar.</i18nString> - <i18nString name="custom_view_selector_desc">Beispiel: "demo-tabbed-views"</i18nString> - <i18nString name="hidden">Versteckt</i18nString> - <i18nString name="fulltext">Einfacher Suchmodus</i18nString> - <i18nString name="sort">Sortieren</i18nString> - <i18nString name="search">Suchen</i18nString> - <i18nString name="edit">Bearbeiten</i18nString> - <i18nString name="headers_mode">Kopfzeilenmodus</i18nString> - <i18nString name="headers_default_mode">Standardkopfzeilenmodus</i18nString> - <i18nString name="is_header_mode_changeable">Erlaube Änderung des Kopfzeilenmodus?</i18nString> - <i18nString name="allow_header_table_mode">Erlaube Tabellenmodus?</i18nString> - <i18nString name="use_default_headers">Eigene Kopfzeilen verwenden?</i18nString> - <i18nString name="task_default_headers">Anzuzeigende Attributmenge auswählen</i18nString> - <i18nString name="task_default_headers_desc">Beispiel: "meta-title,meta-user"</i18nString> - <i18nString name="roles_management_title">Rollen</i18nString> - <i18nString name="filter_update_title">Filter</i18nString> - <i18nString name="additional_filter_update">Zusätzlicher Filter</i18nString> - <i18nString name="filter_header">Aktueller Filter</i18nString> - <i18nString name="roles_allowed">Zulässige Rollen</i18nString> - <i18nString name="item_settings_general">Allgemein</i18nString> - <i18nString name="menu_item_identifier">Identifikationsnummer des Menüeintrages</i18nString> - <i18nString name="remove_additional_filter">Zusatzfilter entfernen</i18nString> - <i18nString name="nodePath">Menüeintrag-URI</i18nString> - <i18nString name="move_dest_uri_new_node">Neuer Knoten</i18nString> - <i18nString name="move_add_node">Hinzufügen</i18nString> - <i18nString name="move_dest_uri">Ziel URI</i18nString> - <i18nString name="duplicate_new_title">Titel der kopierten Ansicht</i18nString> - <i18nString name="duplicate_view_identifier">Identifikator der kopierten Ansicht</i18nString> - <i18nString name="duplicate_view_identifier_desc">Muss einzigartig sein</i18nString> - <i18nString name="name">Titel des Eintrages</i18nString> - <i18nString name="name_desc">Wird im Menü angezeigt</i18nString> - <i18nString name="tab_icon">Ikonen Identifikator der Registerkarte</i18nString> - <i18nString name="display_tab_icon">Zeige die Registerkarte Ikone an?</i18nString> - <i18nString name="tab_name">Titel der Registerkarte</i18nString> - <i18nString name="tab_name_desc">Wird in der Registerkarte angezeigt</i18nString> - <i18nString name="update_filter">Aktualisiere die Ansicht mit dem ausgewählten Filter</i18nString> - <i18nString name="use_custom_view">Eigener Ansicht anwenden?</i18nString> - <i18nString name="custom_view_selector">Konfigurationsidentifikator der eigenen Ansicht</i18nString> - <i18nString name="case_view_search_type">Suchmodus im Fallansicht</i18nString> - <i18nString name="fulltext_advanced">Einfacher und erweiterter Suchmodus</i18nString> - <i18nString name="case_require_title_in_creation">Erforde den Titel beim erzeugen von Fällen?</i18nString> - <i18nString name="case_banned_nets_in_creation">Ausgeschlossene Prozesse</i18nString> - <i18nString name="case_banned_nets_in_creation_desc">Trenne die Prozessidentifikatoren mit einer Komma. z.B.: netz1,netz2</i18nString> - <i18nString name="show_create_case_button">Schaltfläche „Fall erstellen“ anzeigen?</i18nString> - <i18nString name="case_show_more_menu">"Erweiterte Optionen" Taste bei einzelnen Fällen anzeigen</i18nString> - <i18nString name="merge_filters">Mit dem Basisfilter kombinieren?</i18nString> - <i18nString name="task_view_search_type">Suchmodus im Aufgabenansicht</i18nString> - <i18nString name="task_show_more_menu">"Erweiterte Optionen" Taste bei einzelnen Aufgaben anzeigen</i18nString> - <i18nString name="item_settings">Menüeintrageinstellungen</i18nString> - <i18nString name="move_item">Menüeintrag verschieben</i18nString> - <i18nString name="move_item_finish">verschieben</i18nString> - <i18nString name="duplicate_item">Menüeintrag duplizieren</i18nString> - <i18nString name="duplicate_item_finish">duplizieren</i18nString> - <i18nString name="case_view_header">Fallansicht</i18nString> - <i18nString name="task_view_header">Aufgabenansicht</i18nString> - <i18nString name="roles_allowed_desc">Rollen mit Zugriff auf diesen Menüeintrag</i18nString> - <i18nString name="roles_banned">Verbotene Rollen</i18nString> - <i18nString name="roles_banned_desc">Rollen, für die wird den Menüeintrag ausgeblendet</i18nString> - <i18nString name="move_dest_uri_new_node_desc">Nächste URI-Teil angeben</i18nString> - <i18nString name="move_dest_uri_desc">Teile der Ziel URI</i18nString> - </i18n> - - <!-- TRANSITIONS --> - <transition> - <id>initialize</id> - <x>340</x> - <y>220</y> - <label>initialize [await sync]</label> - <icon>hourglass_empty</icon> - <roleRef> - <id>admin</id> - <logic> - <perform>true</perform> - <view>true</view> - <cancel>true</cancel> - <assign>true</assign> - </logic> - </roleRef> - <dataGroup> - <id>view</id> - <dataRef> - <id>filter_case</id> - <logic> - <behavior>forbidden</behavior> - <action trigger="set"> - filterCaseRef: f.filter_case, - menu_name: f.menu_name; - - if (filterCaseRef.value == null || filterCaseRef.value == []) { - return - } - - def filterCase = findCase({it._id.eq(filterCaseRef.value[0])}) - if (!menu_name.value) { - change menu_name value {return filterCase.dataSet["i18n_filter_name"].value} - } - </action> - </logic> - </dataRef> - </dataGroup> - </transition> - - <transition> - <id>item_settings</id> - <x>460</x> - <y>100</y> - <label name="item_settings">Item settings</label> - <icon>settings</icon> - <assignPolicy>auto</assignPolicy> - <roleRef> - <id>admin</id> - <logic> - <perform>true</perform> - <view>true</view> - <cancel>true</cancel> - <assign>true</assign> - </logic> - </roleRef> - <dataGroup> - <id>pre_general</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>menu_item_identifier</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>nodePath</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <x>2</x> - <y>0</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <dataGroup> - <id>general_0</id> - <cols>4</cols> - <layout>grid</layout> - <title name="item_settings_general">General - - menu_name - - editable - - - 0 - 0 - 1 - 2 - - outline - - - - menu_icon - - editable - - - 2 - 0 - 1 - 1 - - outline - - - - menu_icon_preview - - visible - - - 3 - 0 - 1 - 1 - - standard - - - - tab_name - - editable - - - 0 - 1 - 1 - 1 - - outline - - - - use_tab_icon - - editable - - - 1 - 1 - 1 - 1 - 0 - - - - 0 - - - trans: t.this, - iconPreview: f.tab_icon_preview, - icon: f.tab_icon, - useIcon: f.use_tab_icon; - - make iconPreview,visible on trans when { useIcon.value } - make icon,editable on trans when { useIcon.value } - - make iconPreview,hidden on trans when { !useIcon.value } - make icon,hidden on trans when { !useIcon.value } - - - - - - tab_icon - - editable - - - 2 - 1 - 1 - 1 - - outline - - - - tab_icon_preview - - visible - - - 3 - 1 - 1 - 1 - - standard - - - - use_custom_view - - editable - - - 0 - 2 - 1 - 1 - - outline - - - 0 - - - trans: t.this, - caseHeader: f.case_view_header, - caseTaskRef: f.case_view_settings_taskRef, - taskHeader: f.task_view_header, - taskTaskRef: f.task_view_settings_taskRef, - - useTabIcon: f.use_tab_icon, - tabIconPreview: f.tab_icon_preview, - tabName: f.tab_name, - tabIcon: f.tab_icon, - filterSelection: f.filter_autocomplete_selection, - updateFilter: f.update_filter, - selectedFilterPreview: f.selected_filter_preview, - currentFilterHeader: f.filter_header, - currentFilterPreview: f.current_filter_preview, - - use: f.use_custom_view, - selector: f.custom_view_selector; - - make selector,editable on trans when { use.value } - make selector,visible on trans when { !use.value } - - make caseHeader,visible on trans when { !use.value } - make caseHeader,hidden on trans when { use.value } - make caseTaskRef,editable on trans when { !use.value } - make caseTaskRef,hidden on trans when { use.value } - - make taskHeader,visible on trans when { !use.value } - make taskHeader,hidden on trans when { use.value } - make taskTaskRef,editable on trans when { !use.value } - make taskTaskRef,hidden on trans when { use.value } - - make useTabIcon,editable on trans when { !use.value } - make useTabIcon,hidden on trans when { use.value } - make tabIconPreview,visible on trans when { !use.value } - make tabIconPreview,hidden on trans when { use.value } - make tabName,editable on trans when { !use.value } - make tabName,hidden on trans when { use.value } - make tabIcon,editable on trans when { !use.value } - make tabIcon,hidden on trans when { use.value } - make filterSelection,editable on trans when { !use.value } - make filterSelection,hidden on trans when { use.value } - make updateFilter,visible on trans when { !use.value } - make updateFilter,hidden on trans when { use.value } - make selectedFilterPreview,visible on trans when { !use.value } - make selectedFilterPreview,hidden on trans when { use.value } - make currentFilterHeader,visible on trans when { !use.value } - make currentFilterHeader,hidden on trans when { use.value } - make currentFilterPreview,visible on trans when { !use.value } - make currentFilterPreview,hidden on trans when { use.value } - - - - - - custom_view_selector - - visible - - - 1 - 2 - 1 - 3 - - outline - - - - - roles_management - 5 - grid - Roles - - processes_available - - editable - - - 0 - 0 - 2 - 1 - 0 - - outline - - - - roles_available - - editable - - - 1 - 0 - 2 - 1 - 0 - - outline - - - - add_allowed_roles - - editable - - - 2 - 0 - 1 - 1 - 0 - - - - - allowed_roles - - editable - - - 3 - 0 - 1 - 1 - 0 - - outline - - - - remove_allowed_roles - - editable - - - 4 - 0 - 1 - 1 - 0 - - - - - add_banned_roles - - editable - - - 2 - 1 - 1 - 1 - 0 - - - - - banned_roles - - editable - - - 3 - 1 - 1 - 1 - 0 - - outline - - - - remove_banned_roles - - editable - - - 4 - 1 - 1 - 1 - 0 - - - - - - filter_update - 4 - grid - Filter - - filter_autocomplete_selection - - editable - - - 0 - 0 - 1 - 3 - - outline - - - - update_filter - - visible - - - 3 - 0 - 1 - 1 - - standard - - - - selected_filter_preview - - visible - - - 0 - 1 - 1 - 4 - - standard - - - - - current_filter - 4 - grid - - filter_header - - visible - - - 0 - 0 - 1 - 4 - - outline - - - - current_filter_preview - - visible - - - 0 - 1 - 1 - 4 - - standard - - - - - case_view_settings_dataGroup - 4 - grid - - case_view_header - - hidden - - - 0 - 0 - 1 - 4 - - outline - - - - case_view_settings_taskRef - - hidden - - - 0 - 1 - 1 - 4 - - outline - - - - - task_view_settings_dataGroup - 4 - grid - - task_view_header - - hidden - - - 0 - 0 - 1 - 4 - - outline - - - - task_view_settings_taskRef - - hidden - - - 0 - 1 - 1 - 4 - - outline - - - - - - - move_item - 580 - 100 - - move_down - auto - - admin - - true - true - true - true - - - - move - 4 - grid - - move_dest_uri - - editable - required - - - 0 - 0 - 1 - 2 - - outline - - - - move_dest_uri_new_node - - editable - - - 2 - 0 - 1 - 1 - - outline - - - - move_add_node - - editable - - - 3 - 0 - 1 - 1 - - outline - - - - - finish - - - dest: f.move_dest_uri; - - if (dest.value == null || dest.value == []) { - throw new IllegalArgumentException("URI must not be empty!") - } - - String newUri = dest.value.join("/") - newUri = newUri.replace("//","/") - - changeMenuItem useCase uri { newUri } + + + + + use_case_default_headers + Use custom default headers? + true + + + use_custom_view + Use custom view? + false + + + use_tab_icon + Display tab icon? + true + + + use_task_default_headers + Use custom default headers? + true + + + Náhľad ikony + Identifikátor ikony + Identifikátor Material ikony. Zoznam ikon s identifikátormi je dostupný online. + Pridaj k povoleným roliam + Odstráň z povolených rolí + Pridaj k zakázaným roliam + Odstráň zo zakázaných rolí + Vaše procesy + Vyberte proces obsahujúci roly ktoré chcete pridať do zoznamu povolených alebo zakázaných rolí. + Dostupné roly + Názov tlačidla "Nová inštancia" + Identifikátor ikony tlačidla "Nová inštancia" + Náhľad ikony + Predvolené hlavičky + Napríklad: "meta-title,meta-visualId" + Zvoľte nový filter + Cieľové URI + Názov duplikovanej položky + Identifikátor duplikovanej položky + Musí byť jedinečný + Názov položky + Bude zobrazený v menu + Identifikátor ikony v karte + Identifikátor Material ikony. Zoznam ikon s identifikátormi je dostupný online. + Zobraziť ikonu v karte? + Názov položky + Bude zobrazený v karte + Aktualizovať zobrazenie s vybraným filtrom + Použiť vlastné zobrazenie? + Konfiguračný identifikátor vlastného zobrazenia + Napríklad: "demo-tabbed-views" + Typ vyhľadávania prípadov + Skryté + Fulltext + Fulltext a rozšírené + Vyžadovať názov inštancii pri vytváraní? + Zakázané siete pri vytváraní + Uveďte identifikátory procesov oddelené čiarkou. Napríklad: mynet1,mynet2 + Zobraziť tlačidlo na vytvorenie prípadu? + Zobrazovať menu pre prípadovú položku? + Zoraďovanie + Vyhľadávanie + Upravovanie + Zjednotiť filter so základným filtrom? + Typ vyhľadávania úloh + Mód hlavičiek + Predvolený mód hlavičiek + Môže byť mód hlavičiek zmenený? + Povoliť tabuľkový mód pre hlavičky? + Použiť vlastné predvolené hlavičky? + Predvolené hlavičky + Napríklad: "meta-title,meta-user" + Zobrazovať menu pre úlohovú položku? + Nastavenie položky + Roly + Filter + Presunúť položku + Presunúť + Duplikovať položku + Duplikovať + Dodatočný filter + Súčasný filter + Zobrazenie prípadov + Zobrazenie úloh + Povolené roly + Zoznam povolených rolí, ktoré môžu zobraziť túto položku + Zakázané roly + Zoznam zakázaných rolí, ktoré nemôžu zobraziť túto položku + Všeobecné + Identifikátor položky + Odstrániť dodatočný filter + URI položky + Nový uzol + Uveďte názov uzlu, ktorý chcete pridať + Zoznam uzlov reprezentujúce cieľovú URI + Pridať + + + Ikonevorschau + Ikone ID + Material Ikone ID. Liste den Ikonen mit IDs ist online verfügbar. + Zu zulässigen Rollen hinzufügen + Aus zulässigen Rollen entfernen + Zu verbotenen Rollen hinzufügen + Aus verbotenen Rollen entfernen + Ihre Prozesse + Wählen Sie einen Prozess mit Rollen aus, die Sie zu Listen mit zulässigen oder verbotenen Rollen hinzufügen möchten. + Verfügbare Rollen + Schaltflächentitel "Neuer Fall" + Ikone ID + Ikonevorschau + Anzuzeigende Attributmenge auswählen + Neue Filter auswählen + Beispiel: "meta-title,meta-visualId" + Material Ikone ID. Liste den Ikonen mit IDs ist online verfügbar. + Beispiel: "demo-tabbed-views" + Versteckt + Einfacher Suchmodus + Sortieren + Suchen + Bearbeiten + Kopfzeilenmodus + Standardkopfzeilenmodus + Erlaube Änderung des Kopfzeilenmodus? + Erlaube Tabellenmodus? + Eigene Kopfzeilen verwenden? + Anzuzeigende Attributmenge auswählen + Beispiel: "meta-title,meta-user" + Rollen + Filter + Zusätzlicher Filter + Aktueller Filter + Zulässige Rollen + Allgemein + Identifikationsnummer des Menüeintrages + Zusatzfilter entfernen + Menüeintrag-URI + Neuer Knoten + Hinzufügen + Ziel URI + Titel der kopierten Ansicht + Identifikator der kopierten Ansicht + Muss einzigartig sein + Titel des Eintrages + Wird im Menü angezeigt + Ikonen Identifikator der Registerkarte + Zeige die Registerkarte Ikone an? + Titel der Registerkarte + Wird in der Registerkarte angezeigt + Aktualisiere die Ansicht mit dem ausgewählten Filter + Eigener Ansicht anwenden? + Konfigurationsidentifikator der eigenen Ansicht + Suchmodus im Fallansicht + Einfacher und erweiterter Suchmodus + Erforde den Titel beim erzeugen von Fällen? + Ausgeschlossene Prozesse + Trenne die Prozessidentifikatoren mit einer Komma. z.B.: netz1,netz2 + Schaltfläche „Fall erstellen“ anzeigen? + "Erweiterte Optionen" Taste bei einzelnen Fällen anzeigen + Mit dem Basisfilter kombinieren? + Suchmodus im Aufgabenansicht + "Erweiterte Optionen" Taste bei einzelnen Aufgaben anzeigen + Menüeintrageinstellungen + Menüeintrag verschieben + verschieben + Menüeintrag duplizieren + duplizieren + Fallansicht + Aufgabenansicht + Rollen mit Zugriff auf diesen Menüeintrag + Verbotene Rollen + Rollen, für die wird den Menüeintrag ausgeblendet + Nächste URI-Teil angeben + Teile der Ziel URI + + + case_view_settings + 340 + 100 + Case view settings [referenced] + + system + + true + + + + case_view_settings_flex + + + case_view_search_type + + editable + true + + + + 0 + 0 + 1 + + + + + show_create_case_button + + editable + true + + + + 0 + 0 + 1 + + + + + case_show_more_menu + + editable + true + + + + 0 + 0 + 1 + + + + + create_case_button_title + + editable + + + + 0 + 0 + 1 + + + + + create_case_button_icon + + editable + + + + 0 + 0 + 1 + + + + + create_case_button_icon_preview + + visible + + + + 0 + 0 + 1 + + + + + case_require_title_in_creation + + editable + + + + 0 + 0 + 1 + + + + + case_banned_nets_in_creation + + editable + + + + 0 + 0 + 1 + + + + + case_is_header_mode_changeable + + editable + true + + + case_is_header_mode_changeable_set + + + + + + + + + 0 + 0 + 1 + + + + + case_allow_header_table_mode + + editable + true + + + + 0 + 0 + 1 + + + + + case_headers_mode + + editable + true + + + + 0 + 0 + 1 + + + + + case_headers_default_mode + + editable + true + + + + 0 + 0 + 1 + + + + + use_case_default_headers + + editable + + + use_case_default_headers_set + + + + + + + + + 0 + 0 + 1 + + + + + case_default_headers + + editable + + + + 0 + 0 + 1 + + + + + + change_filter + 460 + 340 + [Change filter] + + system + + true + + + + change_filter_flex + + + new_filter_id + + editable + true + + + set_event_0 + + + + + + + + + 0 + 0 + 1 + + + + + + children_order + 580 + 220 + Manage item order + low_priority + auto + + admin + + true + true + true + true + + + + children_order_flex + + + childItemForms + + editable + + + childItemForms_get + + + workflowService.findOne(id).tasks.find { it.transition == "row_for_ordering" }.task } + change childItemForms value { orderedTaskIds } + ]]> + + + + + + 0 + 0 + 1 + + + + + + duplicate_item + 580 + 340 + Duplicate item + content_copy + auto + + admin + + true + true + true + true + + + + duplicate_item_flex + + + duplicate_new_title + + editable + true + + + + 0 + 0 + 1 + + + + + duplicate_view_identifier + + editable + true + + + + 0 + 0 + 1 + + + + + finish + + + - - Move - - - - - duplicate_item - 580 - 340 - - content_copy - auto - - admin - - true - true - true - true - - - - duplicate - 4 - grid - - duplicate_new_title - - editable - required - - - 0 - 0 - 1 - 4 - - outline - - - - duplicate_view_identifier - - editable - required - - - 0 - 1 - 1 - 4 - - outline - - - - - finish - - - identifier: f.duplicate_view_identifier, - title: f.duplicate_new_title; - - duplicateMenuItem(useCase, title.value, identifier.value) + + Duplicate + + + + initialize + 340 + 220 + initialize [await sync] + hourglass_empty + + admin + + true + true + true + true + + + + initialize_flex + + + filter_case + + forbidden + + + filter_case_set + + + + + + + + + 0 + 0 + 1 + + + + + + item_settings + 460 + 100 + Item settings + settings + auto + + admin + + true + true + true + true + + + + item_settings_flex + + + menu_item_identifier + + visible + + + + 0 + 0 + 1 + + + + + nodePath + + visible + + + + 0 + 0 + 1 + + + + + menu_name + + editable + + + + 0 + 0 + 1 + + + + + menu_icon + + editable + + + + 0 + 0 + 1 + + + + + menu_icon_preview + + visible + + + + 0 + 0 + 1 + + + + + tab_name + + editable + + + + 0 + 0 + 1 + + + + + use_tab_icon + + editable + + + use_tab_icon_set + + + + + + + + + 0 + 0 + 1 + + + + + tab_icon + + editable + + + + 0 + 0 + 1 + + + + + tab_icon_preview + + visible + + + + 0 + 0 + 1 + + + + + use_custom_view + + editable + + + use_custom_view_set + + + + + + + + + 0 + 0 + 1 + + + + + custom_view_selector + + visible + + + + 0 + 0 + 1 + + + + + processes_available + + editable + + + + 0 + 0 + 1 + + + + + roles_available + + editable + + + + 0 + 0 + 1 + + + + + add_allowed_roles + + editable + + + + 0 + 0 + 1 + + + + + allowed_roles + + editable + + + + 0 + 0 + 1 + + + + + remove_allowed_roles + + editable + + + + 0 + 0 + 1 + + + + + add_banned_roles + + editable + + + + 0 + 0 + 1 + + + + + banned_roles + + editable + + + + 0 + 0 + 1 + + + + + remove_banned_roles + + editable + + + + 0 + 0 + 1 + + + + + filter_autocomplete_selection + + editable + + + + 0 + 0 + 1 + + + + + update_filter + + visible + + + + 0 + 0 + 1 + + + + + selected_filter_preview + + visible + + + + 0 + 0 + 1 + + + + + filter_header + + visible + + + + 0 + 0 + 1 + + + + + current_filter_preview + + visible + + + + 0 + 0 + 1 + + + + + case_view_header + + hidden + + + + 0 + 0 + 1 + + + + + case_view_settings_taskRef + + hidden + + + + 0 + 0 + 1 + + + + + task_view_header + + hidden + + + + 0 + 0 + 1 + + + + + task_view_settings_taskRef + + hidden + + + + 0 + 0 + 1 + + + + + + move_item + 580 + 100 + Move item + move_down + auto + + admin + + true + true + true + true + + + + move_item_flex + + + move_dest_uri + + editable + true + + + + 0 + 0 + 1 + + + + + move_dest_uri_new_node + + editable + + + + 0 + 0 + 1 + + + + + move_add_node + + editable + + + + 0 + 0 + 1 + + + + + finish + + + - - Duplicate - - - - - change_filter - 460 - 340 - - - system - - true - - - - new_filter_id - - editable - required - - - set_event_0 - - - new_filter_id: f.new_filter_id, - filterTaskRef: f.current_filter_preview, - filterCaseRef: f.filter_case; - - change filterCaseRef value { [new_filter_id.value] } - def filterCase = findCase({it._id.eq(filterCaseRef.value[0])}) - change filterTaskRef value {return [findTask({it.caseId.eq(filterCase.stringId).and(it.transitionId.eq("view_filter"))}).stringId]} - - - - - - - - case_view_settings - 340 - 100 - - - system - - true - - - - case_view_dataGroup - 4 - grid - - case_view_search_type - - editable - required - - - 0 - 0 - 1 - 2 - - outline - - - - show_create_case_button - - editable - required - - - 2 - 0 - 1 - 1 - - outline - - - - case_show_more_menu - - editable - required - - - 3 - 0 - 1 - 1 - - outline - - - - create_case_button_title - - editable - - - 0 - 1 - 1 - 1 - 0 - - outline - - - - create_case_button_icon - - editable - - - 1 - 1 - 1 - 1 - 0 - - outline - - - - create_case_button_icon_preview - - visible - - - 2 - 1 - 1 - 1 - 0 - - standard - - - - case_require_title_in_creation - - editable - - - 3 - 1 - 1 - 1 - 0 - - standard - - - - case_banned_nets_in_creation - - editable - - - 0 - 2 - 1 - 4 - 0 - - outline - - - - - case_view_headers - 5 - grid - - case_is_header_mode_changeable - - editable - required - - trans: t.this, - isChangeable: f.case_is_header_mode_changeable, - mode: f.case_headers_mode, - defaultMode: f.case_headers_default_mode; - - make mode,editable on trans when { isChangeable.value } - make mode,required on trans when { isChangeable.value } - make defaultMode,editable on trans when { isChangeable.value } - make defaultMode,required on trans when { isChangeable.value } - - make mode,hidden on trans when { !isChangeable.value } - make mode,optional on trans when { !isChangeable.value } - make defaultMode,hidden on trans when { !isChangeable.value } - make defaultMode,optional on trans when { !isChangeable.value } - - - - 0 - 0 - 1 - 1 - 0 - - outline - - - - case_allow_header_table_mode - - editable - required - - - 1 - 0 - 1 - 1 - 0 - - outline - - - - case_headers_mode - - editable - required - - - 2 - 0 - 1 - 2 - 0 - - outline - - - - case_headers_default_mode - - editable - required - - - 4 - 0 - 1 - 1 - 0 - - outline - - - - use_case_default_headers - - editable - - trans: t.this, - use: f.use_case_default_headers, - headers: f.case_default_headers; - - make headers,editable on trans when { use.value } - make headers,visible on trans when { !use.value } - - - - 0 - 1 - 1 - 1 - 0 - - outline - - - - case_default_headers - - editable - - - 1 - 1 - 1 - 4 - 0 - - outline - - - - - - - task_view_settings - 340 - 340 - - - system - - true - - - - task_view_dataGroup - 4 - grid - - task_view_search_type - - editable - required - - - 0 - 0 - 1 - 3 - - outline - - - - task_show_more_menu - - editable - required - - - 3 - 0 - 1 - 1 - - outline - - - - - task_view_headers - 5 - grid - - task_is_header_mode_changeable - - editable - required - - trans: t.this, - isChangeable: f.task_is_header_mode_changeable, - mode: f.task_headers_mode, - defaultMode: f.task_headers_default_mode; - - make mode,editable on trans when { isChangeable.value } - make mode,required on trans when { isChangeable.value } - make defaultMode,editable on trans when { isChangeable.value } - make defaultMode,required on trans when { isChangeable.value } - - make mode,hidden on trans when { !isChangeable.value } - make mode,optional on trans when { !isChangeable.value } - make defaultMode,hidden on trans when { !isChangeable.value } - make defaultMode,optional on trans when { !isChangeable.value } - - - - 0 - 0 - 1 - 1 - 0 - - outline - - - - task_allow_header_table_mode - - editable - required - - - 1 - 0 - 1 - 1 - - outline - - - - task_headers_mode - - editable - required - - - 2 - 0 - 1 - 2 - - outline - - - - task_headers_default_mode - - editable - required - - - 4 - 0 - 1 - 1 - - outline - - - - use_task_default_headers - - editable - - trans: t.this, - use: f.use_task_default_headers, - headers: f.task_default_headers; - - make headers,editable on trans when { use.value } - make headers,visible on trans when { !use.value } - - - - 0 - 1 - 1 - 1 - 0 - - outline - - - - task_default_headers - - editable - - - 1 - 1 - 1 - 4 - 0 - - outline - - - - - additional_filter_update - 4 - grid - Additional filter - - additional_filter_autocomplete_selection - - editable - - - 0 - 0 - 1 - 3 - - outline - - - - update_additional_filter - - editable - - - 3 - 0 - 1 - 1 - - standard - - - - selected_additional_filter_preview - - visible - - - 0 - 1 - 1 - 4 - - standard - - - - - current_additional_filter - 4 - grid - - filter_header - - hidden - - - 0 - 0 - 1 - 4 - - outline - - - - current_additional_filter_preview - - visible - - - 0 - 1 - 1 - 4 - - standard - - - - merge_filters - - hidden - - - 0 - 2 - 1 - 1 - - standard - - - - remove_additional_filter - - hidden - - - 1 - 2 - 1 - 1 - - standard - - - - - - children_order - 580 - 220 - - low_priority - auto - - admin - - true - true - true - true - - - - children_order_0 - 4 - grid - - childItemForms - - editable - - forms: f.childItemForms, - ids: f.childItemIds; - - def orderedTaskIds = ids.value?.collect { id -> workflowService.findOne(id).tasks.find { it.transition == "row_for_ordering" }.task } - change forms value { orderedTaskIds } - - - - 0 - 0 - 1 - 4 - - outline - - - - - - row_for_ordering - 741 - 219 - - - system - - true - true - true - true - - - - row_for_ordering_0 - 6 - grid - - menu_item_identifier - - visible - - - 0 - 0 - 1 - 2 - - outline - - - - menu_name_as_visible - - visible - - - 2 - 0 - 1 - 2 - - outline - - - - order_down - - editable - - - 4 - 0 - 1 - 1 - 1 - - outline - - - - order_up - - editable - - - 5 - 0 - 1 - 1 - 1 - - outline - - - - - finish - - - - delegate - - - - - - - uninitialized - 220 - 220 - - 1 - false - - - initialized - 460 - 220 - - 0 - false - - - - - a1 - regular - uninitialized - initialize - 1 - - - a7 - read - initialized - item_settings - 1 - - - a8 - regular - initialize - initialized - 1 - - - a9 - read - initialized - move_item - 1 - - - a10 - read - initialized - duplicate_item - 1 - - - a12 - read - initialized - change_filter - 1 - - - a13 - read - initialized - children_order - 1 - - \ No newline at end of file + + Move + + + + row_for_ordering + 741 + 219 + Row for ordering [referenced] + + system + + true + true + true + true + + + + row_for_ordering_flex + + + menu_item_identifier + + visible + + + + 0 + 0 + 1 + + + + + menu_name_as_visible + + visible + + + + 0 + 0 + 1 + + + + + order_down + + editable + + + + 0 + 0 + 1 + + + + + order_up + + editable + + + + 0 + 0 + 1 + + + + + + task_view_settings + 340 + 340 + Task view settings [referenced] + + system + + true + + + + task_view_settings_flex + + + task_view_search_type + + editable + true + + + + 0 + 0 + 1 + + + + + task_show_more_menu + + editable + true + + + + 0 + 0 + 1 + + + + + task_is_header_mode_changeable + + editable + true + + + task_is_header_mode_changeable_set + + + + + + + + + 0 + 0 + 1 + + + + + task_allow_header_table_mode + + editable + true + + + + 0 + 0 + 1 + + + + + task_headers_mode + + editable + true + + + + 0 + 0 + 1 + + + + + task_headers_default_mode + + editable + true + + + + 0 + 0 + 1 + + + + + use_task_default_headers + + editable + + + use_task_default_headers_set + + + + + + + + + 0 + 0 + 1 + + + + + task_default_headers + + editable + + + + 0 + 0 + 1 + + + + + additional_filter_autocomplete_selection + + editable + + + + 0 + 0 + 1 + + + + + update_additional_filter + + editable + + + + 0 + 0 + 1 + + + + + selected_additional_filter_preview + + visible + + + + 0 + 0 + 1 + + + + + filter_header + + hidden + + + + 0 + 0 + 1 + + + + + current_additional_filter_preview + + visible + + + + 0 + 0 + 1 + + + + + merge_filters + + hidden + + + + 0 + 0 + 1 + + + + + remove_additional_filter + + hidden + + + + 0 + 0 + 1 + + + + + + initialized + 460 + 220 + initialized + 0 + + + uninitialized + 220 + 220 + uninitialized + 1 + + + a1 + regular + uninitialized + initialize + 1 + + + a10 + read + initialized + duplicate_item + 1 + + + a12 + read + initialized + change_filter + 1 + + + a13 + read + initialized + children_order + 1 + + + a7 + read + initialized + item_settings + 1 + + + a8 + regular + initialize + initialized + 1 + + + a9 + read + initialized + move_item + 1 + + \ No newline at end of file diff --git a/src/main/resources/petriNets/engine-processes/user.xml b/src/main/resources/petriNets/engine-processes/user.xml new file mode 100644 index 00000000000..0bcbcadbe1e --- /dev/null +++ b/src/main/resources/petriNets/engine-processes/user.xml @@ -0,0 +1,101 @@ + + user + 1.0.0 + User + person + false + false + User + + admin + + true + true + true + + + + admin + Admin + + + email + Email + + + firstname + First name + + + lastname + Last name + + + groupIds + Groups + + group + + + + + t1 + 368 + 208 + Data + + admin + + true + + + + t1_flex + + + email + + editable + + + + + + firstname + + editable + + + + + + lastname + + editable + + + + + + groupIds + + visible + + + + + + + p1 + 368 + 304 + 1 + + + a1 + read + p1 + t1 + 1 + + \ No newline at end of file diff --git a/src/main/resources/petriNets/engine-processes/validations/validation.xml b/src/main/resources/petriNets/engine-processes/validations/validation.xml new file mode 100644 index 00000000000..a976506b9dd --- /dev/null +++ b/src/main/resources/petriNets/engine-processes/validations/validation.xml @@ -0,0 +1,459 @@ + + validation + 1.0.0 + Validation + home + true + false + + VAL + + + admin + + false + false + true + + + + system + + true + true + true + + + + admin + Admin + + + system + System + + + name + Name + + + num_arguments_groovy + Number of arguments - Groovy + + + num_arguments_javascript + Number of arguments - JavaScript + + + validation_definition_groovy + Validation definition - Groovy + + textarea + + + + validation_definition_javascript + Validation definition - JavaScript + + textarea + + + + validation_type + Type + + + + + + validation_type_set + + + + + + + + + version + Version + + + Meno + Typ + Definícia validácie - Groovy + Počet argumentov - Groovy + Definícia validácie - JavaScript + Počet argumentov - JavaScript + Verzia + Detail + Aktivovať + Deaktivovať + + + Name + Typ + Validierungsdefinition - Groovy + Anzahl der Argumente - Groovy + Validierungsdefinition - JavaScript + Anzahl der Argumente - JavaScript + Ausführung + Detail + Aktivieren + Deaktivieren + + + activate + 580 + 220 + Activate + + admin + + true + + + + onFinish_activate + + + + + + + + + + + + + + deactivate + 580 + 380 + Deactivate + + admin + + true + + + + onFinish_deactivate + + + + + + + + + detail + 300 + 60 + Detail + + detail_flex + + + name + + editable + + + + 0 + 0 + 1 + + + + + version + + editable + + + + 0 + 0 + 1 + + + + + validation_definition_javascript + + editable + + + + 0 + 0 + 1 + + + + + validation_definition_groovy + + editable + + + + 0 + 0 + 1 + + + + + num_arguments_groovy + + editable + + + + 0 + 0 + 1 + + + + + num_arguments_javascript + + editable + + + + 0 + 0 + 1 + + + + + validation_type + + editable + + + + 0 + 0 + 1 + + + + + + init + 300 + 300 + Init + + init_flex + + + name + + editable + true + + + + 0 + 0 + 1 + + + + + validation_definition_groovy + + editable + + + + 0 + 0 + 1 + + + + + validation_definition_javascript + + editable + + + + 0 + 0 + 1 + + + + + version + + editable + + + + 0 + 0 + 1 + + + + + num_arguments_groovy + + editable + + + + 0 + 0 + 1 + + + + + num_arguments_javascript + + editable + + + + 0 + 0 + 1 + + + + + validation_type + + editable + true + + + + 0 + 0 + 1 + + + + + + active + 740 + 300 + active + 0 + + + inactive + 420 + 300 + inactive + 0 + + + initialized + 300 + 180 + initialized + 0 + + + p1 + 180 + 300 + 1 + + + a1 + regular + p1 + init + 1 + + + a2 + regular + init + initialized + 1 + + + a3 + read + initialized + detail + 1 + + + a5 + regular + init + inactive + 1 + + + a6 + regular + inactive + activate + 1 + + + a7 + regular + activate + active + 1 + + + a8 + regular + active + deactivate + 1 + + + a9 + regular + deactivate + inactive + 1 + + \ No newline at end of file diff --git a/src/main/resources/petriNets/insurance_portal_demo.xml b/src/main/resources/petriNets/insurance_portal_demo.xml deleted file mode 100644 index 2887d9f33f1..00000000000 --- a/src/main/resources/petriNets/insurance_portal_demo.xml +++ /dev/null @@ -1,14515 +0,0 @@ - - - examples/insurance/insurance - IPD - Insurance Portal Demo - false - Nové poistenie - - - - - 1 - Výber poistenia - - - 2 - Výpočet poistenia - - - 3 - Zmluva - - - - 1 - Agent - - - 2 - Company - - - - - Obec - 301001 - Názov - - - 301005 - Obec - - - - field: f.301002, - zipcode: f.101001, - obec: f.this; - change field about { - return "L3" as String; - } - - - - - - field: f.this, - other: f.109048; - change other about { - return field?.value?.defaultValue; - } - - - - - PSČ - 101001 - PSČ - - - - field: f.this, - other: f.109047; - change other about { - return field.value; - } - - - - - 301006 - PSČ - - - - Lokalita - 301002 - Typ - - - field: f.this, - coeff: f.201001; - change coeff about { - if (field.value=="L5") - return 3.8 as Double; - if (field.value=="L4") - return 3.4 as Double; - if (field.value=="L3") - return 3.2 as Double; - if (field.value=="L2") - return 3.0 as Double; - if (field.value=="L1") - return 2.8 as Double; - - } - - - - - field: f.this, - coeff: f.201018; - change coeff about { - if (field.value=="L5") - return 3.8 as Double; - if (field.value=="L4") - return 3.4 as Double; - if (field.value=="L3") - return 3.2 as Double; - if (field.value=="L2") - return 3.0 as Double; - if (field.value=="L1") - return 2.8 as Double; - } - - - - - Nachádza sa miesto poistenia mimo obce (extravilán)? - 101002 - - - field: f.this, - coeff: f.201002; - change coeff about { - if (field.value) - return 1.2 as Double; - return 1.0 as Double; - } - - - - - Bolo miesto poistenia postihnuté povodňou alebo záplavou za posledných 10 rokov? - 101003 - - - field: f.this, - coeff: f.201003; - change coeff about { - if (field.value) - return 1.5 as Double; - return 1.0 as Double; - } - - - - - Nachádza sa miesto poistenia vo vzdialenosti kratšej ako 300 m od vodného toku? - 101004 - - - field: f.this, - coeff: f.201004; - change coeff about { - if (field.value) - return 1.3 as Double; - return 1.0 as Double; - } - - - - - 101005 - Koľko rokov žijete v poisťovanej nehnuteľnosti? - Počet rokov - menej ako 1 - 1 až 5 - 6 až 10 - viac ako 10 - 6 až 10 - - - field: f.this, - coeff: f.201005; - change coeff about { - if (field.value=="menej ako 1") - return 1.0 as Double; - if (field.value=="1 až 5") - return 1.0 as Double; - if (field.value=="6 až 10") - return 1.0 as Double; - if (field.value=="viac ako 10") - return 1.0 as Double; - } - - - - - Aký je vzťah poisteného k poisťovanej nehnuteľnosti? - 101006 - Vzťah - vlastník nehnuteľnosti - vlastník ma hypotéku na nehnuteľnosť - poistený je v prenájme - iné - vlastník nehnuteľnosti - - - field: f.this, - coeff: f.201006; - change coeff about { - if (field.value=="vlastník nehnuteľnosti") - return 1.0 as Double; - if (field.value=="vlastník má úver alebo hypotéku na nehnuteľnosť") - return 1.0 as Double; - if (field.value=="poistený je v prenájme") - return 1.1 as Double; - if (field.value=="iné") - return 1.1 as Double; - } - - - - - Koľko dospelých žije v domácnosti? - 101007 - Počet - 1 - 2 - 3 - viac ako 3 - 2 - - - field: f.this, - coeff: f.201007; - change coeff about { - if (field.value=="1") - return 0.95 as Double; - if (field.value=="2") - return 1.0 as Double; - if (field.value=="3") - return 1.05 as Double; - if (field.value=="viac ako 3") - return 1.1 as Double; - } - - - - - Koľko detí žije v domácnosti? - 101008 - Počet - 0 - 1 - 2 - viac ako 2 - 1 - - - field: f.this, - coeff: f.201008; - change coeff about { - if (field.value=="0") - return 1.0 as Double; - if (field.value=="1") - return 1.0 as Double; - if (field.value=="2") - return 1.05 as Double; - if (field.value=="viac ako 2") - return 1.1 as Double; - } - - - - - Žije v poisťovanej domácnosti pes alebo mačka? - 101012 - - - field: f.this, - coeff: f.201012; - change coeff about { - if (field.value) - return 1.05 as Double; - return 1.0 as Double; - } - - - - - Je nehnuteľnosť využívaná aj na podnikanie? - 101014 - - - field: f.this, - coeff: f.201014; - change coeff about { - if (field.value) - return 1.1 as Double; - return 1.0 as Double; - } - - - - - Počet poistných udalostí za posledné 3 roky? - 101016 - Počet - 0 - 1 - 2 a viac - 0 - - - field: f.this, - coeff: f.201016; - change coeff about{ - if (field.value=="0") - return 1.0 as Double; - if (field.value=="1") - return 1.1 as Double; - if (field.value=="2 a viac") - return 1.2 as Double; - } - - - - - - Poistenie nehnuteľnosti - 105005 - Spoluúčasť - 0.00 € - 50.00 € - 150.00 € - 50.00 € - - - field: f.this, - coeff: f.208001; - change coeff about { - if (field.value=="0.00 €") - return 1.1 as Double; - if (field.value=="50.00 €") - return 1.0 as Double; - if (field.value=="150.00 €") - return 0.9 as Double; - } - - - - - Predmet poistenia - 102001 - Typ - byt - rodinný dom - chata - bungalow - - - field: f.this, - coeff: f.202001; - change coeff about { - if (field.value=="byt") - return 1.0 as Double; - if (field.value=="rodinný dom") - return 1.0 as Double; - if (field.value=="chata") - return 1.1 as Double; - if (field.value=="bungalow") - return 1.0 as Double; - if (field.value=="rozostavaná stavba") - return 1.0 as Double; - } - - - - - field: f.this, - coeff: f.201019; - change coeff about { - if (field.value=="byt") - return 0.9 as Double; - if (field.value=="rodinný dom") - return 0.9 as Double; - if (field.value=="chata") - return 1.2 as Double; - if (field.value=="bungalow") - return 0.9 as Double; - if (field.value=="rozostavaná stavba") - return 1.2 as Double; - } - - - - - field: f.this, - coeff: f.103001; - change coeff about { - if (field.value=="byt") - return "byt"; - if (field.value=="rodinný dom") - return "rodinný dom"; - if (field.value=="chata") - return "chata"; - if (field.value=="bungalow") - return "bungalow"; - } - - - - - field: f.this, - coeff: f.102003; - change coeff about { - if (field.value=="byt") - return "škridla"; - } - - - - field: f.102001, - hide: f.103001, - trans: t.363; - make hide,visible on trans when { field.value != null } - - - field: f.102001, - hide: f.105001, - trans: t.155; - make hide,hidden on trans when { field.value=="byt"; } - - - field: f.102001, - hide: f.105002, - trans: t.155; - make hide,hidden on trans when { field.value=="byt"; } - - - field: f.102001, - hide: f.105003, - trans: t.155; - make hide,hidden on trans when { field.value=="byt"; } - - - field: f.102001, - hide: f.305001, - trans: t.155; - make hide,editable on trans when { field.value=="byt"; } - - - field: f.102001, - hide: f.305001, - trans: t.155; - make hide,required on trans when { field.value=="byt"; } - - - field: f.102001, - hide: f.102003, - trans: t.155; - make hide,hidden on trans when { field.value=="byt"; } - - - - field: f.102001, - hide: f.105001, - trans: t.155; - make hide,editable on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.102003, - trans: t.155; - make hide,editable on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.105001, - trans: t.155; - make hide,required on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.105002, - trans: t.155; - make hide,editable on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.105002, - trans: t.155; - make hide,required on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.105003, - trans: t.155; - make hide,editable on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.105003, - trans: t.155; - make hide,required on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.305001, - trans: t.155; - make hide,visible on trans when { field.value!="byt"; } - - - - p1: f.105001, - p2: f.105002, - p3: f.105003, - field: f.305001; - change field about { - return p1.value+p2.value+p3.value as Double; - } - - - - - Konštrukcia múrov - 102002 - Typ - tehla a/alebo betón - porobetón (ytong) - škvarobatón - sklo - drevo - tehla a/alebo betón - - - field: f.this, - coeff: f.202002; - change coeff about { - if (field.value=="tehla a/alebo betón") - return 1.0 as Double; - if (field.value=="porobetón (ytong)") - return 1.05 as Double; - if (field.value=="škvarobatón") - return 1.05 as Double; - if (field.value=="sklo") - return 1.3 as Double; - if (field.value=="drevo") - return 1.5 as Double; - } - - - - - Konštrukcia strechy - 102003 - Typ - škridla - plech - asfalt - sklo - šindel - iné - škridla - - - field: f.this, - coeff: f.202003; - change coeff about { - if (field.value=="škridla") - return 1.0 as Double; - if (field.value=="plech") - return 1.05 as Double; - if (field.value=="asfalt") - return 1.1 as Double; - if (field.value=="sklo") - return 1.15 as Double; - if (field.value=="šindel") - return 1.05 as Double; - if (field.value=="iné") - return 1.1 as Double; - } - - - - - Koľko rokov má nehnuteľnosť? - 102004 - Typ - menej ako 5 - 6 až 10 - 11 až 20 - viac ako 20 - 6 až 10 - - - field: f.this, - coeff: f.202004; - change coeff about { - if (field.value=="menej ako 5") - return 1.0 as Double; - if (field.value=="6 až 10") - return 1.02 as Double; - if (field.value=="11 až 20") - return 1.04 as Double; - if (field.value=="viac ako 20") - return 1.06 as Double; - } - - - - - Koľko izieb má nehnuteľnosť? - 102006 - Počet - 1 - 2 - 3 - 4 - viac ako 4 - - - field: f.this, - coeff: f.202006; - change coeff about { - if (field.value=="1") - return 0.9 as Double; - if (field.value=="2") - return 0.95 as Double; - if (field.value=="3") - return 1.0 as Double; - if (field.value=="4") - return 1.02 as Double; - if (field.value=="viac ako 4") - return 1.05 as Double; - } - - - - - check: f.this, - trans: t.364, - other: f.105006; - make other,visible on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.105036; - make other,editable on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.105036; - make other,required on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.305002; - make other,visible on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.308001; - make other,visible on trans when { check.value != null } - - - - - Koľko kúpeľní má nehnuteľnosť? - 102007 - Počet - 1 - 2 - viac ako 2 - - - field: f.this, - coeff: f.202007; - change coeff about { - if (field.value=="1") - return 1.0 as Double; - if (field.value=="2") - return 1.02 as Double; - if (field.value=="viac ako 2") - return 1.03 as Double; - } - - - - - - Umiestnenie domácnosti - 103001 - Typ - byt - rodinný dom - chata - bungalow - - - field: f.this, - coeff: f.203001; - change coeff about { - if (field.value=="byt") - return 1.0 as Double; - if (field.value=="rodinný dom") - return 1.0 as Double; - if (field.value=="chata") - return 1.25 as Double; - if (field.value=="bungalow") - return 1.0 as Double; - } - - - - - check: f.this, - trans: t.364, - other: f.106002; - make other,visible on trans when { true } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,editable on trans when { true } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,required on trans when { true } - - - - - check: f.this, - trans: t.364, - other: f.306001; - make other,visible on trans when { true } - - - - - check: f.this, - trans: t.364, - other: f.308002; - make other,visible on trans when { true } - - - - - Obývanosť domácnosti - 103002 - trvalá - dočasná - trvalá - - - field: f.this, - coeff: f.203002; - change coeff about { - if (field.value=="trvalá") - return 1.0 as Double; - if (field.value=="dočasná") - return 2.0 as Double; - } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,required on trans when { check.value=="trvalá" } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,editable on trans when { check.value=="trvalá" } - - - - - check: f.this, - trans: t.364, - other: f.106023; - make other,hidden on trans when { check.value=="trvalá" } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,hidden on trans when { check.value=="dočasná" } - - - - - check: f.this, - trans: t.364, - other: f.106023; - make other,required on trans when { check.value=="dočasná" } - - - - - check: f.this, - trans: t.364, - other: f.106023; - make other,editable on trans when { check.value=="dočasná" } - - - - - field: f.106002, - check: f.103002, - other: f.106022; - change other about { - if (check.value=="trvalá") - return field.value as Double; - return 1.0 as Double; - } - - - - - field: f.106002, - check: f.103002, - other: f.106023; - change other about { - if(check.value=="dočasná") - return field.value as Double; - return 1.0 as Double; - } - - - - - field: f.106023, - field2: f.106022, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field.value*field2.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - Je domácnosť zabezpečená funkčným alarmom? - 103004 - false - - - field: f.this, - coeff: f.203004; - change coeff about { - if (field.value) - return 0.97 as Double; - return 1.0 as Double; - } - - - - - field: f.this, - check: f.108005; - change check about { - return field.value; - } - - - - - Má domácnosť na oknách vo výške do 3 metrov od okolitého terénu mreže alebo vonkajšie žalúzie alebo - rolety? - - 103005 - false - - - field: f.this, - coeff: f.203005; - change coeff about { - if (field.value) - return 0.97 as Double; - return 1.0 as Double; - } - - - - - - Územná platnosť poistenia - 104003 - Slovenská republika - Európa - - - field: f.this, - coeff1: f.204002, - coeff: f.204003; - change coeff about { - if (field.value=="Slovenská republika") - return 1.0*coeff1.value as Double; - if (field.value=="Európa") - return 1.2*coeff1.value as Double; - } - - - - - field: f.107003, - coeff: f.204003, - excess: f.208002, - sum: f.308009; - change sum about { - def n = field.value.getDefaultValue().replaceAll("[,€ ]","") as Double; - return ((n*coeff.value*excess.value)/1000.0) as Double; - } - - - - - - Podlahová plocha pivnice - 105001 - m2 - 0 - inrange 0,1000 - - - - field: f.this, - location: f.301002, - coeff: f.205002; - change coeff about { - if (location.value=="L5") - return 850*field.value as Double; - if (location.value=="L4") - return 700*field.value as Double; - if (location.value=="L1") - return 400*field.value as Double; - if (location.value=="L2") - return 500*field.value as Double; - if (location.value=="L3") - return 650*field.value as Double; - } - - - - - p1: f.105001, - p2: f.105002, - p3: f.105003, - field: f.305001; - change field about { - return p1.value+p2.value+p3.value as Double; - } - - - - - Podlahová plocha prízemia - 105002 - m2 - 0 - inrange 0,1000 - - - - field: f.this, - location: f.301002, - coeff: f.205003; - change coeff about { - if (location.value=="L5") - return 1400*field.value as Double; - if (location.value=="L4") - return 900*field.value as Double; - if (location.value=="L1") - return 550*field.value as Double; - if (location.value=="L2") - return 650*field.value as Double; - if (location.value=="L3") - return 800*field.value as Double; - } - - - - - p1: f.105001, - p2: f.105002, - p3: f.105003, - field: f.305001; - change field about { - return p1.value+p2.value+p3.value as Double; - } - - - - - Podlahová plocha všetkých obytných poschodí - 105003 - m2 - Okrem prízemia - 0 - inrange 0,1000 - - - - field: f.this, - location: f.301002, - coeff: f.205004; - change coeff about { - if (location.value=="L5") - return 1200*field.value as Double; - if (location.value=="L4") - return 800*field.value as Double; - if (location.value=="L1") - return 500*field.value as Double; - if (location.value=="L2") - return 550*field.value as Double; - if (location.value=="L3") - return 700*field.value as Double; - } - - - - - p1: f.105001, - p2: f.105002, - p3: f.105003, - field: f.305001; - change field about { - return p1.value+p2.value+p3.value as Double; - } - - - - - Podlahová plocha garáže - 105004 - m2 - 0 - inrange 0,1000 - - - - field: f.this, - location: f.301002, - coeff: f.105007; - change coeff about { - if (location.value=="L5") - return 850*field.value as Double; - if (location.value=="L4") - return 700*field.value as Double; - if (location.value=="L1") - return 400*field.value as Double; - if (location.value=="L2") - return 500*field.value as Double; - if (location.value=="L3") - return 650*field.value as Double; - } - - - - - - - - - - - - - - - - - Celková podlahová plocha - 305001 - m2 - 0 - positive - - - sum: f.this, - check: f.102001, - location: f.301002, - p1: f.205002, - p2: f.205003, - p3: f.205004, - field: f.105006; - change field about { - if (check.value != "byt") - return p1.value+p2.value+p3.value as Double; - if (location.value=="L5") - return 1900*sum.value as Double; - if (location.value=="L4") - return 1300*sum.value as Double; - if (location.value=="L3") - return 950*sum.value as Double; - if (location.value=="L2") - return 700*sum.value as Double; - if (location.value=="L1") - return 650*sum.value as Double; - } - - - - - field: f.this, - location: f.301002, - coeff: f.205001; - change coeff about { - if (location.value=="L5") - return 1900*field.value as Double; - if (location.value=="L4") - return 1300*field.value as Double; - if (location.value=="L1") - return 650*field.value as Double; - if (location.value=="L2") - return 700*field.value as Double; - if (location.value=="L3") - return 950*field.value as Double; - } - - - - field: f.305001, - trans: t.363, - other: f.106003; - make other,visible on trans when { field.value > 0 } - - - field: f.305001, - trans: t.363, - other: f.106003; - make other,editable on trans when { field.value == null } - - - field: f.305001, - trans: t.363, - other: f.106003; - make other,editable on trans when { field.value == 0 as Double } - - - - field: f.this, - check: f.410001, - other: f.106003; - change other about { - if (check.value == "Nehnutelnost a domacnost" ) - return field.value as Double; - return other.value as Double; - } - - - - - f1: f.305001, - f2: f.106003, - other: f.308005; - change other about { - return Boolean.logicalAnd(f1.value != 0.0, f2.value != 0.0); - } - - - - - - - Garáž - 105035 - - - field: f.this, - other: f.105007, - trans: t.414; - make other,visible on trans when { field.value } - - - - - field: f.this, - other: f.305003, - trans: t.414; - make other,visible on trans when { field.value } - - - - - field: f.this, - other: f.105008, - trans: t.414; - make other,visible on trans when { field.value } - - - - - field: f.this, - other: f.305019, - trans: t.414; - make other,visible on trans when { field.value } - - - - - field: f.this, - other: f.105007, - trans: t.414; - make other,hidden on trans when { field.value == false } - - - - - field: f.this, - other: f.305003, - trans: t.414; - make other,hidden on trans when { field.value == false } - - - - - field: f.this, - other: f.105008, - trans: t.414; - make other,hidden on trans when { field.value == false } - - - - - field: f.this, - other: f.305019, - trans: t.414; - make other,hidden on trans when { field.value == false } - - - - - - field: f.this, - other: f.105007; - change other about { null; } - - - - - field: f.this, - other: f.305003; - change other about { null; } - - - - - field: f.this, - other: f.105008; - change other about { null; } - - - - - field: f.this, - other: f.305019; - change other about { null; } - - - - - field: f.this, - other: f.105004; - change other about { null; } - - - - - - Garáž - 105007 - Odporúčaná poistná suma - positive - - - field: f.this, - sum: f.305019; - change sum about { - return field.value as Double; - } - - - - - Garáž - 305019 - Poistná suma - inrange 1,80000 - - - field: f.305019, - check: f.105035, - exces: f.208001, - coeff: f.208003, - other: f.305003; - change other about { - return ((field.value*coeff.value*exces.value)/1000.0) as Double; - } - - - - - Garáž - 305003 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - Rovnaké miesto poistenia garáže? - 105008 - true - - - field: f.this, - coeff: f.208003; - change coeff about { - if (field.value) - return 1.0 as Double; - return 1.1 as Double; - } - - - - - field: f.305019, - check: f.105035, - exces: f.208001, - coeff: f.208003, - other: f.305003; - change other about { - return ((field.value*coeff.value*exces.value)/1000.0) as Double; - } - - - - - Hospodárska budova - 105009 - - - field: f.this, - coeff: f.205007; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - - field: f.this, - other: f.105010, - trans: t.413; - make other,editable on trans when { field.value } - - - - - field: f.this, - other: f.105010, - trans: t.413; - make other,required on trans when { field.value } - - - - - field: f.this, - other: f.305004, - trans: t.413; - make other,visible on trans when { field.value } - - - - - - field: f.this, - other: f.105010, - trans: t.413; - make other,hidden on trans when { !field.value } - - - - - field: f.this, - other: f.305004, - trans: t.413; - make other,hidden on trans when { !field.value } - - - - - - field: f.this, - other: f.105010; - change other about { null; } - - - - - field: f.this, - other: f.305004; - change other about { null; } - - - - - Hospodárska budova - 105010 - Poistná suma - positive - - - field: f.this, - coeff: f.205007, - excess: f.208001, - sum: f.305004; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Hospodárska budova - 305004 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Altánok - 105011 - - - field: f.this, - coeff: f.205008; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - - field: f.this, - other: f.105012, - trans: t.413; - make other,editable on trans when { field.value } - - - - - field: f.this, - other: f.305005, - trans: t.413; - make other,visible on trans when { field.value } - - - - - - field: f.this, - other: f.105012, - trans: t.413; - make other,hidden on trans when { return !field.value } - - - - - field: f.this, - other: f.305005, - trans: t.413; - make other,hidden on trans when { return !field.value } - - - - - - field: f.this, - other: f.105012; - change other about { null; } - - - - - field: f.this, - other: f.305005; - change other about { null; } - - - - - Altánok - 105012 - Poistná suma - positive - - - field: f.this, - coeff: f.205008, - excess: f.208001, - sum: f.305005; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Altánok - 305005 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Prístrešok - 105013 - - - field: f.this, - coeff: f.205009; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - - Prístrešok - 105014 - Poistná suma - positive - - - field: f.this, - coeff: f.205009, - excess: f.208001, - sum: f.305006; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Prístrešok - 305006 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Chodník, parkovacia plocha - 105015 - - - field: f.this, - coeff: f.205010; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Chodník, parkovacia plocha - 105016 - Poistná suma - positive - - - field: f.this, - coeff: f.205010, - excess: f.208001, - sum: f.305007; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Chodník, parkovacia plocha - 305007 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Sauna - 105017 - - - field: f.this, - coeff: f.205011; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Sauna - 105018 - Poistná suma - positive - - - field: f.this, - coeff: f.205011, - excess: f.208001, - sum: f.305008; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Sauna - 305008 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Elektrická brána - 105019 - - - field: f.this, - coeff: f.205012; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Elektrická brána, oplotenie - 105020 - Poistná suma - positive - - - field: f.this, - coeff: f.205012, - excess: f.208001, - sum: f.305009; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Elektrická brána, oplotenie - 305009 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Tenisový kurt - 105021 - - - field: f.this, - coeff: f.205013; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Tenisový kurt - 105022 - Poistná suma - positive - - - field: f.this, - coeff: f.205013, - excess: f.208001, - sum: f.305010; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Tenisový kurt - 305010 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Vonkajší bazén - 105023 - - - field: f.this, - coeff: f.205014; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Vonkajší bazén - 105024 - Poistná suma - positive - - - field: f.this, - coeff: f.205014, - excess: f.208001, - sum: f.305011; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Vonkajší bazén - 305011 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Studňa - 105025 - - - field: f.this, - coeff: f.205015; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Studňa - 105026 - Poistná suma - positive - - - field: f.this, - coeff: f.205015, - excess: f.208001, - sum: f.305012; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Studňa - 305012 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Žumpa, septik - 105027 - - - field: f.this, - coeff: f.205016; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Žumpa, septik - 105028 - Poistná suma - positive - - - field: f.this, - coeff: f.205016, - excess: f.208001, - sum: f.305013; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Žumpa, septik - 305013 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Iné - 105029 - - - field: f.this, - coeff: f.205017; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Iné - 105030 - Poistná suma - positive - - - field: f.this, - coeff: f.205017, - excess: f.208001, - sum: f.305014; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Iné - 305014 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - - Celková poistná suma - inrange 1,50000 - 305017 - - - Celkové poistné - 305018 - - - - Stavebné materialy - 105031 - - - Stavebné materiály - 105032 - Poistná suma - inrange 1,5000 - - - field: f.this, - coeff: f.205018, - excess: f.208001, - sum: f.305015; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - Stavebné materiály - 305015 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - Stavebné a záhradné mechanizmy - 105033 - - - Stavebné a záhradné mechanizmy - 105034 - Poistná suma - inrange 1,7000 - - - field: f.this, - coeff: f.205019, - excess: f.208001, - sum: f.305016; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - Stavebné a záhradné mechanizmy - 305016 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - - Poistenie domácnosti - 106001 - 0.00 € - 50.00 € - 150.00 € - 50.00 € - Spoluúčasť - - - field: f.this, - coeff: f.208002; - change coeff about { - if (field.value=="0.00 €") - return 1.1 as Double; - if (field.value=="50.00 €") - return 1.0 as Double; - if (field.value=="150.00 €") - return 0.9 as Double; - } - - - - - field: f.106022, - field2: f.106023, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field2.value*field.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - check: f.this, - trans: t.364, - other: f.106002; - make other,visible on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,editable on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,required on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.106023; - make other,editable on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.106023; - make other,required on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.306001; - make other,visible on trans when { check.value != null } - - - - - - Odporúčaná poistná suma - 106002 - Poistná suma - positive - - - field: f.106002, - check: f.103002, - other: f.106022; - change other about { - if (check.value=="trvalá") - return field.value as Double; - return 1.0 as Double; - } - - - - - field: f.106002, - check: f.103002, - other: f.106023; - change other about { - if(check.value=="dočasná") - return field.value as Double; - return 1.0 as Double; - } - - - - - - Poistná suma - 106022 - Poistná suma - inrange 1,300000 - - - field: f.106022, - field2: f.106023, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field.value*field2.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - - Poistná suma - 106023 - Poistná suma - inrange 1,50000 - - - field: f.106023, - field2: f.106022, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field.value*field2.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - Poistenie domácnosti - 306001 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - - Celková podlahová plocha - 106003 - 0 - positive - - - - - - - - - - - - - - - - - - - - - - field: f.this, - coeff: f.106002; - change coeff about { - if (field.value > 100) - return 25000 + (field.value - 100) * 100 as Double; - return 250*field.value as Double; - } - - - - - f1: f.305001, - f2: f.106003, - other: f.308005; - change other about { - return Boolean.logicalAnd(f1.value != 0.0, f2.value != 0.0); - } - - - - - Cennosti - 106004 - - - Cennosti - 106005 - inrange 0,10000 - - Poistná suma - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Cennosti - 306002 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Umelecké diela - 106006 - - - Umelecké diela - 106007 - Poistná suma - inrange 0,5000 - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Umelecké diela - 306003 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Elektronické a optické zariadenia - 106008 - - - Elektronické a optické zariadenia - 106009 - Poistná suma - inrange 0,10000 - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Elektronické a optické zariadenia - 306004 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Špecialne sklá a presklenie - 106010 - - - Špeciálne sklá a presklenie - 106011 - inrange 0,2000 - Poistná suma - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Špeciálne sklá a presklenie - 306005 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Záhradné vybavenie a nábytok - 106012 - - - Záhradé vybavenie a nábytok - 106013 - inrange 0,2000 - Poistná suma - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Záhradé vybavenie a nábytok - 306006 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Elektromotory v domácich spotrebičoch - 106014 - - - Elektromotory v domácich spotrebičoch - 106015 - inrange 0,300 - Poistná suma - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Elektromotory v domácich spotrebičoch - 306007 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Stavebné súčasti domácnosti - 106016 - - - Stavebné súčasti domácností - 106017 - inrange 0,30000 - Poistná suma - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Stavebné súčasti domácností - 306008 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Športové náradie - 106018 - - - Športové náradie - 106019 - inrange 0,5000 - Poistná suma - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - športové náradie - 306009 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Iné - 106020 - - - Iné - 106021 - Poistná suma - inrange 0,2000 - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Iné - 306010 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Celková poistná suma - 106024 - positive - - - Celkové poistné - 106025 - positive - - - - - Poistenie zodpovednosti z vlastníctva nehnuteľnosti do výšky - 107001 - Poistná suma - 120,000.00 € - 60,000.00 € - 30,000.00 € - 15,000.00 € - 0.00 € - - - field: f.this, - coeff: f.204001; - change coeff about { - if (field.value == "0.00 €") - return 0.0 as Double; - return 0.2 as Double; - } - - - - - field: f.this, - coeff: f.204001, - excess: f.208001, - sum: f.308008; - change sum about { - def n = field.value.getDefaultValue().replaceAll("[,€ ]","") as Double; - return ((n*coeff.value*excess.value)/1000.0) as Double; - } - - - - - check: f.this, - trans: t.364, - other: f.308008; - make other,hidden on trans when { check.value == "0.00 €" } - - - - - check: f.this, - trans: t.364, - other: f.308008; - make other,visible on trans when { check.value != "0.00 €" } - - - - - check: f.107003, - check2: f.107001, - trans: t.364, - other: f.308003; - make other,hidden on trans when { Boolean.logicalAnd(check.value == "0.00 €", check2.value == "0.00 €") } - - - - - Zodpovednosť za škodu členov domácnosti - 107003 - Eur - 120,000.00 € - 60,000.00 € - 30,000.00 € - 15,000.00 € - 0.00 € - - - field: f.this, - coeff: f.204002; - change coeff about { - if (field.value == "0.00 €") - return 0.0 as Double; - return 0.2 as Double; - } - - - - - field: f.107003, - coeff: f.204003, - excess: f.208002, - sum: f.308009; - change sum about { - def n = field.value.getDefaultValue().replaceAll("[,€ ]","") as Double; - return ((n*coeff.value*excess.value)/1000.0) as Double; - } - - - - - check: f.this, - trans: t.363, - other: f.104003; - make other,editable on trans when { check.value != "0.00 €" } - - - - - check: f.this, - trans: t.363, - other: f.104003; - make other,required on trans when { check.value != "0.00 €" } - - - - - check: f.this, - trans: t.363, - other: f.104003; - make other,hidden on trans when { check.value == "0.00 €" } - - - - - check: f.this, - other: f.104003; - change other about { - if (check.value == "0.00 €") - return null; - return other.value; - } - - - - - check: f.this, - trans: t.364, - other: f.308009; - make other,visible on trans when { check.value != "0.00 €" } - - - - - check: f.this, - trans: t.364, - other: f.308003; - make other,visible on trans when { check.value != "0.00 €" } - - - - - check: f.this, - trans: t.364, - other: f.308009; - make other,hidden on trans when { check.value == "0.00 €" } - - - - - check: f.107003, - check2: f.107001, - trans: t.364, - other: f.308003; - make other,hidden on trans when { Boolean.logicalAnd(check.value == "0.00 €", check2.value == "0.00 €") } - - - - - - field: f.this, - other: f.308009; - change other about { null; } - - - - - check: f.this, - trans: t.364, - other: f.108005; - make other,visible on trans when { check.value != null } - - - - - - Celkové poistenie nehnuteľnosti - 308001 - Poistné - - - s1: f.308001, - s2: f.308002, - s3: f.308003, - sum: f.308004; - change sum about { - return s1.value+s2.value+s3.value as Double; - } - - - - - Poistenie nehnuteľnosti - 305002 - Poistné - 0 - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - Odporúčaná poistná suma - 105006 - Poistná suma - positive - - - field: f.105006, - other: f.105036; - change other about { - return field.value as Double; - } - - - - - Poistná suma - 105036 - Poistná suma - inrange 1,700000 - - - field: f.105036, - excess: f.208001, - hhc: f.202009, - sadzba: f.201019, - bic: f.201017, - sum: f.305002; - change sum about { - return ((field.value*excess.value*hhc.value*bic.value*sadzba.value)/1000.0) as Double; - } - - - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - Celkové poistenie domácnosti - 308002 - Poistné - - - s1: f.308001, - s2: f.308002, - s3: f.308003, - sum: f.308004; - change sum about { - return s1.value+s2.value+s3.value as Double; - } - - - - - Poistenie zodpovednosti z vlastníctva nehnuteľnosti - 308008 - Poistné - - - c1: f.308008, - c2: f.308009, - sum: f.308003; - change sum about { - return c1.value+c2.value as Double; - } - - - - - Zodpovednosť za škodu členov domácnosti - 308009 - Poistné - - - c1: f.308008, - c2: f.308009, - sum: f.308003; - change sum about { - return c1.value+c2.value as Double; - } - - - - - Celkové poistenie zodpovednosti za škodu - 308003 - Poistné - - - s1: f.308001, - s2: f.308002, - s3: f.308003, - sum: f.308004; - change sum about { - return s1.value+s2.value+s3.value as Double; - } - - - - - ROČNÉ POISTNÉ CELKOM - 308004 - - - c1: f.308004, - c2: f.208004, - c3: f.208008, - c4: f.208005, - c5: f.208006, - c6: f.208007, - c7: f.203004, - sum: f.308006; - change sum about { - return (Math.round(100.0*c1.value*c2.value*c3.value*c4.value*c5.value*c6.value*c7.value/4.0)/100.0)*4.0 as - Double; - } - - - - - PERIODICITA PLATBY POISTNÉHO - 108001 - ročná - polročná - štvrťročná - ročná - - - field: f.this, - coeff: f.208004; - change coeff about { - if (field.value == "ročná") - return 0.95 as Double; - if (field.value == "polročná") - return 0.99 as Double; - if (field.value == "štvrťročná") - return 1.0 as Double; - } - - - - - check: f.108001, - field: f.308006, - sum: f.308010; - change sum about { - if (check.value=="ročná") - return field.value as Double; - if (check.value=="polročná") - return field.value/2 as Double; - if (check.value=="štvrťročná") - return field.value/4 as Double; - } - - - - - c1: f.308004, - c2: f.208004, - c3: f.208008, - c4: f.208005, - c5: f.208006, - c6: f.208007, - c7: f.203004, - sum: f.308006; - change sum about { - return (Math.round(100.0*c1.value*c2.value*c3.value*c4.value*c5.value*c6.value*c7.value/4.0)/100.0)*4.0 as - Double; - } - - - - - KOMPLETNÉ POISTENIE - 308005 - - - field: f.this, - coeff: f.208008; - change coeff about { - if (field.value) - return 0.95 as Double; - return 1.0 as Double; - } - - - - - c1: f.308004, - c2: f.208004, - c3: f.208008, - c4: f.208005, - c5: f.208006, - c6: f.208007, - c7: f.203004, - sum: f.308006; - change sum about { - return (Math.round(100.0*c1.value*c2.value*c3.value*c4.value*c5.value*c6.value*c7.value/4.0)/100.0)*4.0 as - Double; - } - - - - - ZĽAVA ZA INÉ POISTENIE V PREMIUM - 108002 - - - field: f.this, - coeff: f.208005; - change coeff about { - if (field.value) - return 0.95 as Double; - return 1.0 as Double; - } - - - - - c1: f.308004, - c2: f.208004, - c3: f.208008, - c4: f.208005, - c5: f.208006, - c6: f.208007, - c7: f.203004, - sum: f.308006; - change sum about { - return (Math.round(100.0*c1.value*c2.value*c3.value*c4.value*c5.value*c6.value*c7.value/4.0)/100.0)*4.0 as - Double; - } - - - - - - ZABEZPEČENIE DOMÁCNOSTI ALARMOM - 108005 - - - - OBCHODNÁ ZĽAVA - 108003 - 0% - 5% - 10% - 15% - 20% - 25% - - - field: f.this, - coeff: f.208006; - change coeff about { - if (field.value=="0%") - return 1.0 as Double; - if (field.value=="5%") - return 0.95 as Double; - if (field.value=="10%") - return 0.9 as Double; - if (field.value=="15%") - return 0.85 as Double; - if (field.value=="20%") - return 0.8 as Double; - if (field.value=="25%") - return 0.75 as Double; - } - - - - - c1: f.308004, - c2: f.208004, - c3: f.208008, - c4: f.208005, - c5: f.208006, - c6: f.208007, - c7: f.203004, - sum: f.308006; - change sum about { - return (Math.round(100.0*c1.value*c2.value*c3.value*c4.value*c5.value*c6.value*c7.value/4.0)/100.0)*4.0 as - Double; - } - - - - - AKCIOVÁ ZĽAVA - 108004 - - - field: f.this, - coeff: f.208007; - change coeff about { - if (field.value) - return 0.9 as Double; - return 1.0 as Double; - } - - - - - c1: f.308004, - c2: f.208004, - c3: f.208008, - c4: f.208005, - c5: f.208006, - c6: f.208007, - c7: f.203004, - sum: f.308006; - change sum about { - return (Math.round(100.0*c1.value*c2.value*c3.value*c4.value*c5.value*c6.value*c7.value/4.0)/100.0)*4.0 as - Double; - } - - - - - BEŽNÉ POISTNÉ - 308006 - - - check: f.108001, - field: f.308006, - sum: f.308010; - change sum about { - if (check.value=="ročná") - return field.value as Double; - if (check.value=="polročná") - return field.value/2 as Double; - if (check.value=="štvrťročná") - return field.value/4 as Double; - } - - - - - Výška splátky poistného - 308010 - inrange 20,inf - - - - Koeficient - Lokalita nehnutelnosť - 201001 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Lokalita sadzba domácnosť - 201018 - 1 - - - Koeficient - Lokalita sadzba nehnutelnosť - 201019 - 1 - - - Koeficient - Nachádza sa mimo obce (extravilán)? - 201002 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Bolo miesto poistenia postihnuté povodňou za posledných 10 rokov? - 201003 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Nachádza nehnuteľnosť sa vo vzdialenosti kratšej ako 300 m od vodného toku? - 201004 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Koľko rokov žijete v poisťovanej nehnuteľnosti? - 201005 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Aký je vzťah poisteného k poisťovanej nehnuteľnosti? - 201006 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Koľko dospelých žije v domácnosti? - 201007 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Koľko detí žije v domácnosti? - 201008 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Žije v poisťovanej domácnosti pes alebo mačka? - 201012 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Je nehnuteľnosť využívaná aj na podnikanie? - 201014 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - - Koeficient - Počet poistných udalostí za posledné 3 roky? - 201016 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - ZÁKLADNÉ INFORMÁCIE koeficient - 201017 - 1 - - - field: f.105036, - excess: f.208001, - hhc: f.202009, - sadzba: f.201019, - bic: f.201017, - sum: f.305002; - change sum about { - return ((field.value*excess.value*hhc.value*bic.value*sadzba.value)/1000.0) as Double; - } - - - - - field: f.106022, - field2: f.106023, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field.value*field2.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - - Koeficient - Poistenie nehnuteľnosti - spoluúčasť - 208001 - 1 - - - Koeficient - Predmet poistenia - 202001 - 1 - - - c1: f.202001, - c2: f.202002, - c3: f.202003, - c4: f.202004, - c6: f.202006, - c7: f.202007, - sum: f.202009; - change sum about { - return c1.value*c2.value*c3.value*c4.value*c6.value*c7.value; - } - - - - - Koeficient - Konštrukcia múrov - 202002 - 1 - - - c1: f.202001, - c2: f.202002, - c3: f.202003, - c4: f.202004, - c6: f.202006, - c7: f.202007, - sum: f.202009; - change sum about { - return c1.value*c2.value*c3.value*c4.value*c6.value*c7.value; - } - - - - - Koeficient - Konštrukcia strechy - 202003 - 1 - - - c1: f.202001, - c2: f.202002, - c3: f.202003, - c4: f.202004, - c6: f.202006, - c7: f.202007, - sum: f.202009; - change sum about { - return c1.value*c2.value*c3.value*c4.value*c6.value*c7.value; - } - - - - - Koeficient - Koľko rokov má nehnuteľnosť? - 202004 - 1.02 - - - c1: f.202001, - c2: f.202002, - c3: f.202003, - c4: f.202004, - c6: f.202006, - c7: f.202007, - sum: f.202009; - change sum about { - return c1.value*c2.value*c3.value*c4.value*c6.value*c7.value; - } - - - - - Koeficient - Koľko izieb má nehnuteľnosť? - 202006 - 1 - - - c1: f.202001, - c2: f.202002, - c3: f.202003, - c4: f.202004, - c6: f.202006, - c7: f.202007, - sum: f.202009; - change sum about { - return c1.value*c2.value*c3.value*c4.value*c6.value*c7.value; - } - - - - - Koeficient - Koľko kúpeľní má nehnuteľnosť? - 202007 - 1 - - - c1: f.202001, - c2: f.202002, - c3: f.202003, - c4: f.202004, - c6: f.202006, - c7: f.202007, - sum: f.202009; - change sum about { - return c1.value*c2.value*c3.value*c4.value*c6.value*c7.value; - } - - - - - NEHNUTEĽNOSŤ koeficient - 202009 - 0.945 - - - field: f.105036, - excess: f.208001, - hhc: f.202009, - sadzba: f.201019, - bic: f.201017, - sum: f.305002; - change sum about { - return ((field.value*excess.value*hhc.value*bic.value*sadzba.value)/1000.0) as Double; - } - - - - - - Koeficient - Poistenie domácnosti - spoluúčasť - 208002 - 1 - - - field: f.106022, - field2: f.106023, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field.value*field2.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - Koeficient - Umiestnenie domácnosti - 203001 - 1.0 - - - c1: f.203001, - c2: f.203002, - c5: f.203005, - sum: f.203006; - change sum about { - return c1.value*c2.value*c5.value; - } - - - - - Koeficient - Obývanosť domácnosti - 203002 - 1.0 - - - c1: f.203001, - c2: f.203002, - c5: f.203005, - sum: f.203006; - change sum about { - return c1.value*c2.value*c5.value; - } - - - - - Koeficient - Je domácnosť zabezpečená funkčným alarmom? - 203004 - 1.0 - - - - - - - - - - - - - - - Koeficient - Má domácnosť na oknách vo výške do 3 metrov od okolitého terénu mreže / vonkajšie žalúzie - alebo rolety? - - 203005 - 1.0 - - - c1: f.203001, - c2: f.203002, - c5: f.203005, - sum: f.203006; - change sum about { - return c1.value*c2.value*c5.value; - } - - - - - DOMÁCNOSŤ koeficient - 203006 - 0.95 - - - field: f.106022, - field2: f.106023, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field.value*field2.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - - Koeficient - Poistenie zodpovednosti z vlastníctva nehnuteľnosti - 204001 - - - Koeficient - Zodpovednosť za škodu členov domácnosti - 204002 - 0 - - - Koeficient - Územná platnosť poistenia - 204003 - 1 - - - Koeficient - Zodpovednosť celkovo - 204004 - 0 - - - - Koeficient - PERIODICITA PLATBY POISTNÉHO - 208004 - 0.95 - - - Koeficient - ZĽAVA ZA INÉ POISTENIE V PREMIUM - 208005 - 1 - - - Koeficient - OBCHODNÁ ZĽAVA - 208006 - 1 - - - Koeficient - AKCIOVÁ ZĽAVA - 208007 - 1 - - - Koeficient - KOMPLETNÉ POISTENIE - 208008 - 1 - - - - Koeficient - Lokalita - byt - 205001 - 0 - - - field: f.105036, - excess: f.208001, - hhc: f.202009, - sadzba: f.201019, - bic: f.201017, - sum: f.305002; - change sum about { - return ((field.value*excess.value*hhc.value*bic.value*sadzba.value)/1000.0) as Double; - } - - - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - Koeficient - Lokalita - pivnica - 205002 - 0 - - - Koeficient - Lokalita - prízemie - 205003 - 0 - - - Koeficient - Lokalita - obytné poschodie - 205004 - 0 - - - Koeficient - Lokalita - garáž - 205005 - - - Koeficient - Garáž - 205006 - - - Koeficient - Garáž umiestnenie - 208003 - 1 - - - Koeficient - Hospodárska budova - 205007 - - - Koeficient - Altánok - 205008 - - - Koeficient - Prístrešok - 205009 - - - Koeficient - Chodník, parkovacia plocha - 205010 - - - - Koeficient - Sauna - 205011 - - - Koeficient - Elektrická brána, oplotenie - 205012 - - - Koeficient - Tenisový kurt - 205013 - - - Koeficient - Vonkajší bazén - 205014 - - - Koeficient - Studňa - 205015 - - - Koeficient - Žumpa, septik - 205016 - - - Koeficient - Iné - 205017 - - - Koeficient - Stavebné materiály - 205018 - - - Koeficient - Stavebné a záhradné mechanizmy - 205019 - - - - Koeficient - Cennosti - 206001 - - - Koeficient - Umelecké diela - 206002 - - - Koeficient - Elektronické a optické zariadneia - 206003 - - - Koeficient - Špecialne sklá a presklenie - 206004 - - - Koeficient - Záhradné vybavenie a nábytok - 206005 - - - Koeficient - Elektromotory v domácich spotrebičoch - 206006 - - - Koeficient - Stavebné súčasti domácností - 206007 - - - Koeficient - Športové náradie - 206008 - - - Koeficient - Iné - 206009 - - - Koeficient - Domácnosť - lokalita - 206010 - - - - Koeficient - Poistenie zodpovednosti z vlastníctva nehnuteľnosti - 207001 - - - Koeficient - Zodpovednosť za škodu členov domácnosti - 207002 - - - - - - - Číslo zmluvy - 309001 - 0000000000 - - - field: f.this; - generate "Insurance.offerId",once into field - - - - - field: f.this, - other: f.308007; - change other about { - return field.value; - } - - - - - Začiatok poistenia - 109001 - - - Poistenie na dobu určitú - 109002 - - - field: f.this, - other: f.109003, - trans: t.1661; - make other,editable on trans when { field.value } - - - - - field: f.this, - other: f.109003, - trans: t.332; - make other,editable on trans when { field.value } - - - - - field: f.this, - other: f.109003, - trans: t.1618; - make other,editable on trans when { field.value } - - - - - field: f.this, - other: f.109003, - trans: t.1661; - make other,hidden on trans when { !field.value } - - - - - field: f.this, - other: f.109003, - trans: t.332; - make other,hidden on trans when { !field.value } - - - - - field: f.this, - other: f.109003, - trans: t.1618; - make other,hidden on trans when { !field.value } - - - - - Koniec poistenia - 109003 - - - V prospech - 109004 - Údaje o vinkulácii - - - Číslo úverovej zmluvy - 109005 - Údaje o vinkulácii - - - 109060 - Zriaďuje sa indexácia poistnej sumy? - - - Spôsob platenia - 109006 - prevodom - vkladom alebo poštovou poukážkou - - - field: f.this, - other: f.109065, - trans: t.1661; - make other,editable on trans when { field.value == "vkladom alebo poštovou poukážkou" } - - - - - field: f.this, - other: f.109065, - trans: t.332; - make other,editable on trans when { field.value == "vkladom alebo poštovou poukážkou" } - - - - - field: f.this, - other: f.109065, - trans: t.1618; - make other,editable on trans when { field.value == "vkladom alebo poštovou poukážkou" } - - - - - - field: f.this, - other: f.109065, - trans: t.1661; - make other,required on trans when { field.value == "vkladom alebo poštovou poukážkou" } - - - - - field: f.this, - other: f.109065, - trans: t.332; - make other,required on trans when { field.value == "vkladom alebo poštovou poukážkou" } - - - - - field: f.this, - other: f.109065, - trans: t.1618; - make other,required on trans when { field.value == "vkladom alebo poštovou poukážkou" } - - - - - - field: f.this, - other: f.109065, - trans: t.1661; - make other,hidden on trans when { field.value == "prevodom" } - - - - - field: f.this, - other: f.109065, - trans: t.332; - make other,hidden on trans when { field.value == "prevodom" } - - - - - field: f.this, - other: f.109065, - trans: t.1618; - make other,hidden on trans when { field.value == "prevodom" } - - - - - - field: f.this, - other: f.109065; - change other about { return null; } - - - - - 109065 - Pôvod finančných prostriedkov - - - 109066 - Osobitné vyjadrenia týkajúce sa poisteného alebo poistníka - area - - - 109067 - Poistník udeľuje poisťovateľovi súhlas so spracovaním osobných údajov na marketingové účely - - - - - Typ subjektu - 109007 - Poistník - fyzická osoba - právnická osoba - fyzická osoba podnikateľ (SZČO) - fyzická osoba - - - field: f.109020, - f_1: f.109007, - f_2: f.109021; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - - check: f.109007, - field: f.109058, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109058, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109058, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109007, - field: f.109058, - trans: t.588; - make field,required on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109007, - field: f.109058, - trans: t.588; - make field,editable on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109007, - field: f.109058; - change field about { - if (check.value == "fyzická osoba") - return null; - return field.value; - } - - - - - - check: f.109007, - field: f.109012, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109012, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109012, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109007, - field: f.109012, - trans: t.588; - make field,required on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109007, - field: f.109012, - trans: t.588; - make field,editable on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109007, - field: f.109012; - change field about { - if (check.value == "fyzická osoba") - return null; - return field.value; - } - - - - - - check: f.109007, - field: f.109061, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109061, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109061, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109007, - field: f.109061, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109007, - field: f.109061; - change field about { - if (check.value == "právnická osoba") - return field.value; - return null; - } - - - - - - check: f.109007, - field: f.109062, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109062, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109062, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109007, - field: f.109062, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109007, - field: f.109062; - change field about { - if (check.value == "právnická osoba") - return field.value; - return null; - } - - - - - Titul pred menom - 109008 - Poistník - - - field: f.109020, - f_1: f.109008, - f_2: f.109022; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Titul za menom - 109009 - Poistník - - - field: f.109020, - f_1: f.109009, - f_2: f.109023; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Meno - 109010 - Poistník - - - field: f.109020, - f_1: f.109010, - f_2: f.109024; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Priezvisko - 109011 - Poistník - - - field: f.109020, - f_1: f.109011, - f_2: f.109025; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Obchodné meno - 109012 - Poistník - - - field: f.109020, - f_1: f.109012, - f_2: f.109026; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Štátna príslušnosť - 109013 - Poistník - SR - CZ - HU - PL - AT - Iná - - - field: f.109020, - f_1: f.109013, - f_2: f.109027; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Dátum narodenia - 109014 - Poistník - - - field: f.109020, - f_1: f.109014, - f_2: f.109028; - change f_2 about { - if (field.value == false) - return f_1.value; - return f_2.value; - } - - - - - Rodné číslo - 109015 - Poistník - - - field: f.109020, - f_1: f.109015, - f_2: f.109029; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Typ preukazu - 109016 - Poistník - pas - OP - iné - - - check: f.this, - other: f.109015, - trans: t.588; - make other,hidden on trans when { check.value != "OP" } - - - - - check: f.this, - other: f.109015, - trans: t.588; - make other,editable on trans when { check.value == "OP" } - - - - - check: f.this, - other: f.109015, - trans: t.588; - make other,required on trans when { check.value == "OP" } - - - - - field: f.109020, - f_1: f.109016, - f_2: f.109030; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Číslo preukazu - 109017 - Poistník - - - field: f.109020, - f_1: f.109017, - f_2: f.109031; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Telefónne číslo - 109018 - Poistník - telnumber - - - field: f.109020, - f_1: f.109018, - f_2: f.109032; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Email - 109019 - email - Poistník - - - field: f.109020, - f_1: f.109019, - f_2: f.109033; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Štát - 109060 - Poistník - - - V zastúpení - 109061 - Poistník - - - Funkcia - 109062 - Poistník - - - - Poistený je iná osoba - 109020 - false - Poistený a poistenec sú rôzne osoby - - - field: f.this, - other: f.109021, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109022, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109023, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109024, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109024, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109025, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109025, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109027, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109027, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109028, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109028, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109029, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109029, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109030, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109030, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109031, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109031, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109032, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109033, - trans: t.588; - make other,editable on trans when { field.value } - - - - - field: f.109020, - f_1: f.109007, - f_2: f.109021; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109008, - f_2: f.109022; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109009, - f_2: f.109023; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109010, - f_2: f.109024; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109011, - f_2: f.109025; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109012, - f_2: f.109026; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109013, - f_2: f.109027; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109014, - f_2: f.109028; - change f_2 about { - if (field.value == false) - return f_1.value; - return f_2.value; - } - - - - - field: f.109020, - f_1: f.109015, - f_2: f.109029; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109016, - f_2: f.109030; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109017, - f_2: f.109031; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109018, - f_2: f.109032; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109019, - f_2: f.109033; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109058, - f_2: f.109059; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109061, - f_2: f.109063; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109062, - f_2: f.109064; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.this, - other: f.109021, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109022, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109023, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109024, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109025, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109026, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109027, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109028, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109029, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109030, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109031, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109032, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109033, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109059, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109063, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109064, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - - IČO - 109058 - Poistník - - - field: f.109020, - f_1: f.109058, - f_2: f.109059; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - 109061 - V zastúpení - Poistník - - - field: f.109020, - f_1: f.109061, - f_2: f.109063; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - 109062 - Funkcia konateľa - Poistník - - - field: f.109020, - f_1: f.109062, - f_2: f.109064; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - - Typ subjektu - 109021 - Poistený - fyzická osoba - právnická osoba - fyzická osoba podnikateľ (SZČO) - fyzická osoba - - - - check: f.109021, - field: f.109059, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109059, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109059, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109021, - field: f.109059, - trans: t.588; - make field,required on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109059, - trans: t.588; - make field,editable on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109059; - change field about { - if (check.value == "fyzická osoba") - return null; - return field.value; - } - - - - - - check: f.109021, - field: f.109026, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109026, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109026, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109021, - field: f.109026, - trans: t.588; - make field,required on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109026, - trans: t.588; - make field,editable on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109026; - change field about { - if (check.value == "fyzická osoba") - return null; - return field.value; - } - - - - - - check: f.109021, - field: f.109029, - trans: t.588; - make field,hidden on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109029, - trans: t.588; - make field,required on trans when { check.value == "fyzická osoba" } - - - - - check: f.109021, - field: f.109029, - trans: t.588; - make field,editable on trans when { check.value == "fyzická osoba" } - - - - - check: f.109021, - field: f.109029, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109029; - change field about { - if (check.value == "fyzická osoba") - return field.value; - return null; - } - - - - - - check: f.109021, - field: f.109063, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109063, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109063, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109021, - field: f.109063, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109063; - change field about { - if (check.value == "právnická osoba") - return field.value; - return null; - } - - - - - - check: f.109021, - field: f.109064, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109064, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109064, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109021, - field: f.109064, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109064; - change field about { - if (check.value == "právnická osoba") - return field.value; - return null; - } - - - - - Titul pred menom - 109022 - Poistený - - - Titul za menom - 109023 - Poistený - - - Meno - 109024 - Poistený - - - Priezvisko - 109025 - Poistený - - - Obchodné meno - 109026 - Poistený - - - Štátna príslušnosť - 109027 - Poistený - SK - CZ - HU - PL - Iná - SK - - - Dátum narodenia - 109028 - Poistený - - - Rodné číslo - 109029 - - Poistený - - - Typ preukazu - 109030 - Poistený - pas - OP - iné - - - check: f.this, - other: f.109029, - trans: t.588; - make other,hidden on trans when { check.value != "OP" } - - - - - check: f.this, - check2: f.109020, - other: f.109029, - trans: t.588; - make other,editable on trans when { Boolean.logicalAnd(check.value == "OP", check2.value as Boolean) } - - - - - check: f.this, - check2: f.109020, - other: f.109029, - trans: t.588; - make other,required on trans when { Boolean.logicalAnd(check.value == "OP", check2.value as Boolean) } - - - - - Číslo preukazu - 109031 - Poistený - - - Telefónne číslo - 109032 - Poistený - telnumber - - - Email - 109033 - email - Poistený - - - IČO - 109059 - Poistený - - - 109063 - V zastúpení - Poistený - - - 109064 - Funkcia konateľa - Poistený - - - - - Rovnaká ako miesto poistenia - 109035 - Adresa trvalého pobytu - true - - - field: f.this, - other: f.109036, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109037, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109038, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109039, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109036, - trans: t.588; - make other,required on trans when { !field.value } - - - field: f.this, - other: f.109037, - trans: t.588; - make other,required on trans when { !field.value } - - - field: f.this, - other: f.109038, - trans: t.588; - make other,required on trans when { !field.value } - - - field: f.this, - other: f.109039, - trans: t.588; - make other,required on trans when { !field.value } - - - - field: f.this, - other: f.109036, - trans: t.588; - make other,hidden on trans when { field.value } - - - field: f.this, - other: f.109037, - trans: t.588; - make other,hidden on trans when { field.value } - - - field: f.this, - other: f.109038, - trans: t.588; - make other,hidden on trans when { field.value } - - - field: f.this, - other: f.109039, - trans: t.588; - make other,hidden on trans when { field.value } - - - - - field: f.109035, - f_1: f.109045, - f_2: f.109036; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - field: f.this, - f_1: f.109046, - f_2: f.109037; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - field: f.this, - f_1: f.109047, - f_2: f.109038; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - field: f.this, - f_1: f.109048, - f_2: f.109039; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - Ulica - 109036 - Trvalý pobyt/Sídlo - - - field: f.109034, - f_1: f.109036, - f_2: f.109041; - change f_2 about { - if (field.value) - return f_1.value as String; - return f_2.value; - } - - - - - Súpisné a orientačné číslo - 109037 - Trvalý pobyt/Sídlo - - - field: f.109034, - f_1: f.109037, - f_2: f.109042; - change f_2 about { - if (field.value) - return f_1.value as String; - return f_2.value; - } - - - - - PSČ - 109038 - Trvalý pobyt/Sídlo - - - field: f.109034, - f_1: f.109038, - f_2: f.109043; - change f_2 about { - if (field.value) - return f_1.value as String; - return f_2.value; - } - - - - - Obec - 109039 - Trvalý pobyt/Sídlo - - - field: f.109034, - f_1: f.109039, - f_2: f.109044; - change f_2 about { - if (field.value) - return f_1.value as String; - return f_2.value; - } - - - - - - Rovnaká ako trvalý pobyt - 109034 - Korešpondenčná adresa - true - - - field: f.this, - other: f.109041, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109042, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109043, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109044, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109041, - trans: t.588; - make other,required on trans when { !field.value } - - - field: f.this, - other: f.109042, - trans: t.588; - make other,required on trans when { !field.value } - - - field: f.this, - other: f.109043, - trans: t.588; - make other,required on trans when { !field.value } - - - field: f.this, - other: f.109044, - trans: t.588; - make other,required on trans when { !field.value } - - - - field: f.this, - other: f.109041, - trans: t.588; - make other,hidden on trans when { field.value } - - - field: f.this, - other: f.109042, - trans: t.588; - make other,hidden on trans when { field.value } - - - field: f.this, - other: f.109043, - trans: t.588; - make other,hidden on trans when { field.value } - - - field: f.this, - other: f.109044, - trans: t.588; - make other,hidden on trans when { field.value } - - - - - field: f.109034, - f_1: f.109036, - f_2: f.109041; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - field: f.109034, - f_1: f.109037, - f_2: f.109042; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - field: f.109034, - f_1: f.109038, - f_2: f.109043; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - field: f.109034, - f_1: f.109039, - f_2: f.109044; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - Ulica - 109041 - Korešpondenčná adresa - - - Súpisné a orientačné číslo - 109042 - Korešpondenčná adresa - - - PSČ - 109043 - Korešpondenčná adresa - - - Obec - 109044 - Korešpondenčná adresa - - - - Ulica - 109045 - Miesto poistenia - - - field: f.109035, - f_1: f.109045, - f_2: f.109036; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - Súpisné a orientačné číslo - 109046 - Miesto poistenia - - - field: f.109035, - f_1: f.109046, - f_2: f.109037; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - PSČ - 109047 - Miesto poistenia - - - field: f.109035, - f_1: f.109047, - f_2: f.109038; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - Obec - 109048 - Miesto poistenia - - - field: f.109035, - f_1: f.109048, - f_2: f.109039; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - - Ulica - 109054 - Garáž - - - Súpisné a orientačné číslo - 109055 - Garáž - - - PSČ - 109056 - Garáž - - - Obec - 109057 - Garáž - - - - Variabilný symbol - 308007 - - - Dátum valuty - 110001 - - - Predčíslo účtu - 110002 - - - Číslo účtu - 110003 - - - Predčíslo protiúčtu - 110004 - - - Číslo protiúčtu - 110005 - - - Kód banky protiúčtu - 110006 - - - Názov protiúčtu - 110007 - - - Suma - 110008 - - - Mena - 110009 - - - Kurz - 110010 - - - Zostatok - 110011 - - - Popis obratu - 110012 - - - E2E reference - 110013 - - - Variabilný symbol - 110014 - - - Konštantný symbol - 110015 - - - Špecifický symbol - 110016 - - - Poznámka - 110017 - - - Číslo výpisu - 110018 - - - Identifikácia protiúčtu 1 - 110019 - - - Identifikácia protiúčtu 2 - 110020 - - - Identifikácia protiúčtu 3 - 110021 - - - Identifikácia protiúčtu 4 - 110022 - - - Správa pre prijímateľa 1 - 110023 - - - Správa pre prijímateľa 2 - 110024 - - - Správa pre prijímateľa 3 - 110025 - - - Správa pre prijímateľa 4 - 110026 - - - - Dátum dojednania návrhu na uzavretie poistnej zmluvy - 309002 - - - - Ponuka PDF - 309003 - Automaticky generované - - - self: f.this; - generate "Insurance.offerPDF",always into self - - - - - Zmluva PDF - 309004 - Automaticky generované - - - self: f.this; - generate "Insurance.draftPDF",always into self - - - - - - - Dummy - 410001 - - - - Only Property - Only Household - Property and Household - - - - - - 2 - 260 - 300 - - home - 1 - auto - - 1 - - - 1 - - true - - - - 1 - - start - - 410001 - - forbidden - - trans: t.this; - changeCaseProperty "icon" about { trans.icon } - - - self: f.this; - change self about { "Nehnutelnost" } - - - - - - - - 4 - 180 - 900 - - weekend - 2 - auto - - 1 - - - 1 - - true - - - - 1 - - start - - 410001 - - forbidden - - trans: t.this; - changeCaseProperty "icon" about { trans.icon } - - - self: f.this; - change self about { "Domacnost" } - - - - - - - - 3 - 180 - 580 - - home weekend - 3 - auto - - 1 - - - 1 - - true - - - - 1 - - start - - 410001 - - forbidden - - trans: t.this; - changeCaseProperty "icon" about { trans.icon } - - - self: f.this; - change self about { "Nehnutelnost a domacnost" } - - - - - - - - 154 - 620 - 60 - - 1 - auto - - 2 - - - 1 - - true - - - - 1 - - start - - - 101001 - - editable - required - - - - - - 301005 - - editable - required - - - - - 101002 - - editable - required - - - - - 2 - - start - - - 101003 - - editable - required - - - - - 101004 - - editable - required - - - - - 101005 - - editable - required - - - - - 101006 - - editable - required - - - - - 101007 - - editable - required - - - - - 101008 - - editable - required - - - - - 101012 - - editable - required - - - - - 101014 - - editable - required - - - - - 101016 - - editable - required - - - - - - - 155 - 620 - 220 - - 2 - auto - - 2 - - - 1 - - true - - - - 2 - - start - - - 102001 - - required - editable - - - f1: f.102001, - f2: f.106001, - other: f.308005; - change other about { - return Boolean.logicalAnd(f1.value != null, f2.value != null); - } - - - - - other: f.410001, - field: f.this; - change field choices { - if (other.value == "Nehnutelnost") - return field.choices + ["rozostavaná stavba"]; - return field.choices; - } - - - - - - - 105005 - - editable - - - - - 102006 - - editable - required - - - - - 102007 - - editable - required - - - - - 107001 - - editable - required - - - - - 3 - - left - - - 105001 - - editable - required - - - - - 105002 - - editable - required - - - - - 105003 - - editable - required - - - - - 305001 - - visible - - - - - 102002 - - editable - - - - - 102003 - - hidden - - - - - 102004 - - editable - - - - - - - 414 - 620 - 380 - - 3 - auto - - 2 - - - 1 - - true - - - - 1 - - start - - - 105031 - - editable - - - field: f.this, - coeff: f.205018; - change coeff about { - if (field.value) - return 3.0 as Double; - return 0 as Double; - } - - - - - check: f.105031, - other: f.105032, - trans: t.414; - make other,editable on trans when { check.value } - - - - - check: f.105031, - other: f.105032, - trans: t.414; - make other,required on trans when { check.value } - - - - - check: f.105031, - other: f.105032, - trans: t.414; - make other,hidden on trans when { !check.value } - - - - - check: f.105031, - other: f.305015, - trans: t.414; - make other,visible on trans when { check.value } - - - - - check: f.105031, - other: f.305015, - trans: t.414; - make other,hidden on trans when { !check.value } - - - - - - check: f.105031, - other: f.105032; - change other about { null; } - - - - - check: f.105031, - other: f.105032; - change other about { null; } - - - - - - - 2 - - start - - - 105032 - - hidden - - - - - 305015 - - hidden - - - - - 3 - - start - - - 105033 - - editable - - - field: f.this, - coeff: f.205019; - change coeff about { - if (field.value) - return 5.0 as Double; - return 0 as Double; - } - - - - - check: f.105033, - other: f.105034, - trans: t.414; - make other,editable on trans when { check.value } - - - - - check: f.105033, - other: f.105034, - trans: t.414; - make other,required on trans when { check.value } - - - - - check: f.105033, - other: f.105034, - trans: t.414; - make other,hidden on trans when { !check.value } - - - - - check: f.105033, - other: f.305016, - trans: t.414; - make other,visible on trans when { check.value } - - - - - check: f.105033, - other: f.305016, - trans: t.414; - make other,hidden on trans when { !check.value } - - - - - - check: f.105033, - other: f.105034; - change other about { null; } - - - - - check: f.105033, - other: f.105034; - change other about { null; } - - - - - - - 4 - - start - - - 105034 - - hidden - - - - - 305016 - - hidden - - - - - 1 - - start - - - 105035 - - editable - - - isGarage: f.105035, - trans: t.414, - other: f.105004; - make other,editable on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.105004; - make other,required on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.105004; - make other,hidden on trans when { !isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.105008; - make other,editable on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.105008; - make other,hidden on trans when { !isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.105007; - make other,required on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.105007; - make other,hidden on trans when { !isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.305019; - make other,editable on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.305019; - make other,required on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.305019; - make other,hidden on trans when { !isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.305003; - make other,visible on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.305003; - make other,hidden on trans when { !isGarage.value } - - - - - - - 101 - - start - - - 105004 - - hidden - - - - - 105008 - - hidden - - - - isGarage: f.105008, - trans: t.588, - other: f.109054; - make other,editable on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109055; - make other,editable on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109056; - make other,editable on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109057; - make other,editable on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109054; - make other,required on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109055; - make other,required on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109056; - make other,required on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109057; - make other,required on trans when { !isGarage.value } - - - - - - isGarage: f.105008, - trans: t.588, - other: f.109054; - make other,hidden on trans when { isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109055; - make other,hidden on trans when { isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109056; - make other,hidden on trans when { isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109057; - make other,hidden on trans when { isGarage.value } - - - - - - - 105007 - - hidden - - - - - 305019 - - hidden - - - - - - 305003 - - hidden - - - - - - - 413 - 620 - 540 - - 4 - auto - - 2 - - - 1 - - true - - - - 2 - - start - - - 105009 - - editable - - - - idTrue: f.105009, - trans: t.413, - other: f.105010; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105009, - trans: t.413, - other: f.305004; - make other,visible on trans when { idTrue.value } - - - - - idTrue: f.105009, - trans: t.413, - other: f.105010; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105009, - trans: t.413, - other: f.305004; - make other,hidden on trans when { !idTrue.value } - - - - - - - 102 - - start - - - 105010 - - hidden - - - field: f.this, - check: f.105009, - exces: f.208001, - other: f.305004; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305004 - - hidden - - - - - 3 - - start - - - 105011 - - editable - - - - idTrue: f.105011, - trans: t.413, - other: f.105012; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105011, - trans: t.413, - other: f.105012; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105011, - trans: t.413, - other: f.305005; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105011, - trans: t.413, - other: f.105012; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105011, - trans: t.413, - other: f.305005; - make other,hidden on trans when { !idTrue.value } - - - - - - - 103 - - start - - - 105012 - - hidden - - - field: f.this, - check: f.105011, - exces: f.208001, - other: f.305005; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305005 - - hidden - - - - - 4 - - start - - - 105013 - - editable - - - - idTrue: f.105013, - trans: t.413, - other: f.105014; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105013, - trans: t.413, - other: f.305006; - make other,visible on trans when { idTrue.value } - - - - - idTrue: f.105013, - trans: t.413, - other: f.105014; - make other,required on trans when { idTrue.value } - - - - - - idTrue: f.105013, - trans: t.413, - other: f.105014; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105013, - trans: t.413, - other: f.305006; - make other,hidden on trans when { !idTrue.value } - - - - - - - 104 - - start - - - 105014 - - hidden - - - field: f.this, - check: f.105013, - exces: f.208001, - other: f.305006; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305006 - - hidden - - - - - 5 - - start - - - 105015 - - editable - - - - idTrue: f.105015, - trans: t.413, - other: f.105016; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105015, - trans: t.413, - other: f.105016; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105015, - trans: t.413, - other: f.305007; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105015, - trans: t.413, - other: f.105016; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105015, - trans: t.413, - other: f.305007; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105015, - other: f.105016; - change other about { null; } - - - - - idTrue: f.105015, - other: f.305007; - change other about { null; } - - - - - - - 105 - - start - - - 105016 - - hidden - - - field: f.this, - check: f.105015, - exces: f.208001, - other: f.305007; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305007 - - hidden - - - - - 6 - - start - - - - 105017 - - editable - - - - idTrue: f.105017, - trans: t.413, - other: f.105018; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105017, - trans: t.413, - other: f.105018; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105017, - trans: t.413, - other: f.305008; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105017, - trans: t.413, - other: f.105018; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105017, - trans: t.413, - other: f.305008; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105017, - other: f.105018; - change other about { null; } - - - - - idTrue: f.105017, - other: f.305008; - change other about { null; } - - - - - - - 106 - - start - - - 105018 - - hidden - - - field: f.this, - check: f.105017, - exces: f.208001, - other: f.305008; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305008 - - hidden - - - - - 7 - - start - - - 105019 - - editable - - - - idTrue: f.105019, - trans: t.413, - other: f.105020; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105019, - trans: t.413, - other: f.105020; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105019, - trans: t.413, - other: f.305009; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105019, - trans: t.413, - other: f.105020; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105019, - trans: t.413, - other: f.305009; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105019, - other: f.105020; - change other about { null; } - - - - - idTrue: f.105019, - other: f.305009; - change other about { null; } - - - - - - - 107 - - start - - - 105020 - - hidden - - - field: f.this, - check: f.105019, - exces: f.208001, - other: f.305009; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305009 - - hidden - - - - - 8 - - start - - - 105021 - - editable - - - - idTrue: f.105021, - trans: t.413, - other: f.105022; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105021, - trans: t.413, - other: f.105022; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105021, - trans: t.413, - other: f.305010; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105021, - trans: t.413, - other: f.105022; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105021, - trans: t.413, - other: f.305010; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105021, - other: f.105022; - change other about { null; } - - - - - idTrue: f.105021, - other: f.305010; - change other about { null; } - - - - - - - 108 - - start - - - 105022 - - hidden - - - field: f.this, - check: f.105021, - exces: f.208001, - other: f.305010; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305010 - - hidden - - - - - 9 - - start - - - 105023 - - editable - - - - idTrue: f.105023, - trans: t.413, - other: f.105024; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105023, - trans: t.413, - other: f.105024; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105023, - trans: t.413, - other: f.305011; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105023, - trans: t.413, - other: f.105024; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105023, - trans: t.413, - other: f.305011; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105023, - other: f.105024; - change other about { null; } - - - - - idTrue: f.105023, - other: f.305011; - change other about { null; } - - - - - - - 109 - - start - - - 105024 - - hidden - - - field: f.this, - check: f.105023, - exces: f.208001, - other: f.305011; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305011 - - hidden - - - - - 10 - - start - - - 105025 - - editable - - - - idTrue: f.105025, - trans: t.413, - other: f.105026; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105025, - trans: t.413, - other: f.105026; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105025, - trans: t.413, - other: f.305012; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105025, - trans: t.413, - other: f.105026; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105025, - trans: t.413, - other: f.305012; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105025, - other: f.105026; - change other about { null; } - - - - - idTrue: f.105025, - other: f.305012; - change other about { null; } - - - - - - - 110 - - start - - - 105026 - - hidden - - - field: f.this, - check: f.105025, - exces: f.208001, - other: f.305012; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305012 - - hidden - - - - - 11 - - start - - - 105027 - - editable - - - - idTrue: f.105027, - trans: t.413, - other: f.105028; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105027, - trans: t.413, - other: f.105028; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105027, - trans: t.413, - other: f.305013; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105027, - trans: t.413, - other: f.105028; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105027, - trans: t.413, - other: f.305013; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105027, - other: f.105028; - change other about { null; } - - - - - idTrue: f.105027, - other: f.305013; - change other about { null; } - - - - - - - 111 - - start - - - 105028 - - hidden - - field: f.this, - check: f.105027, - exces: f.208001, - other: f.305013; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305013 - - hidden - - - - - 12 - - start - - - 105029 - - editable - - - - idTrue: f.105029, - trans: t.413, - other: f.105030; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105029, - trans: t.413, - other: f.105030; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105029, - trans: t.413, - other: f.305014; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105029, - trans: t.413, - other: f.105030; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105029, - trans: t.413, - other: f.305014; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105029, - other: f.105030; - change other about { null; } - - - - - idTrue: f.105029, - other: f.305014; - change other about { null; } - - - - - - - 112 - - start - - - 105030 - - hidden - - field: f.this, - check: f.105029, - exces: f.208001, - other: f.305014; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305014 - - hidden - - - - - 2 - - - - 305017 - - visible - - - - - 305018 - - visible - - - - - - - 363 - 620 - 700 - - 5 - auto - - 2 - - - 1 - - true - - - - 5 - - start - - - 103001 - - editable - required - - - - - 106001 - - editable - required - - - - - 5 - - start - - - 107003 - - editable - required - - - - - 104003 - - hidden - - - - - 6 - - start - - - 103002 - - editable - required - - - - - 106003 - - editable - required - - - - - 5 - - start - true - - - 103004 - - editable - required - - - - - 5 - - start - true - - - 103005 - - editable - required - - - - - - - 421 - 620 - 860 - - 6 - auto - - 2 - - - 1 - - true - - - - 1 - - start - - - 106004 - - editable - - - idTrue: f.106004, - trans: t.421, - other: f.106005; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106004, - trans: t.421, - other: f.106005; - make other,required on trans when { idTrue.value } - - - idTrue: f.106004, - trans: t.421, - other: f.306002; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106004, - trans: t.421, - other: f.106005; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106004, - trans: t.421, - other: f.306002; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106004, - other: f.106005; - change other about { null; } - - - idTrue: f.106004, - other: f.306002; - change other about { null; } - - - - - - 2 - - start - - - 106005 - - hidden - - field: f.this, - check: f.106004, - exces: f.208002, - other: f.306002; - change other about { - if (check.value) - return ((field.value*exces.value*4.2)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306002 - - hidden - - - - - 3 - - start - - - 106006 - - editable - - - idTrue: f.106006, - trans: t.421, - other: f.106007; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106006, - trans: t.421, - other: f.106007; - make other,required on trans when { idTrue.value } - - - idTrue: f.106006, - trans: t.421, - other: f.306003; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106006, - trans: t.421, - other: f.106007; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106006, - trans: t.421, - other: f.306003; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106006, - other: f.106007; - change other about { null; } - - - idTrue: f.106006, - other: f.306003; - change other about { null; } - - - - - - 4 - - start - - - 106007 - - hidden - - field: f.this, - check: f.106006, - exces: f.208002, - other: f.306003; - change other about { - if (check.value) - return ((field.value*exces.value*4.2)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306003 - - hidden - - - - - 5 - - start - - - 106008 - - editable - - - idTrue: f.106008, - trans: t.421, - other: f.106009; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106008, - trans: t.421, - other: f.106009; - make other,required on trans when { idTrue.value } - - - idTrue: f.106008, - trans: t.421, - other: f.306004; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106008, - trans: t.421, - other: f.106009; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106008, - trans: t.421, - other: f.306004; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106008, - other: f.106009; - change other about { null; } - - - idTrue: f.106008, - other: f.306004; - change other about { null; } - - - - - - 6 - - start - - - 106009 - - hidden - - field: f.this, - check: f.106008, - exces: f.208002, - other: f.306004; - change other about { - if (check.value) - return ((field.value*exces.value*4.2)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306004 - - hidden - - - - - 7 - - start - - - 106010 - - editable - - - idTrue: f.106010, - trans: t.421, - other: f.106011; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106010, - trans: t.421, - other: f.106011; - make other,required on trans when { idTrue.value } - - - idTrue: f.106010, - trans: t.421, - other: f.306005; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106010, - trans: t.421, - other: f.106011; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106010, - trans: t.421, - other: f.306005; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106010, - other: f.106011; - change other about { null; } - - - idTrue: f.106010, - other: f.306005; - change other about { null; } - - - - - - 8 - - start - - - 106011 - - hidden - - field: f.this, - check: f.106010, - exces: f.208002, - other: f.306005; - change other about { - if (check.value) - return ((field.value*exces.value*25.0)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306005 - - hidden - - - - - 9 - - start - - - 106012 - - editable - - - idTrue: f.106012, - trans: t.421, - other: f.106013; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106012, - trans: t.421, - other: f.106013; - make other,required on trans when { idTrue.value } - - - idTrue: f.106012, - trans: t.421, - other: f.306006; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106012, - trans: t.421, - other: f.106013; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106012, - trans: t.421, - other: f.306006; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106012, - other: f.106013; - change other about { null; } - - - idTrue: f.106012, - other: f.306006; - change other about { null; } - - - - - - 10 - - start - - - 106013 - - hidden - - field: f.this, - check: f.106012, - exces: f.208002, - other: f.306006; - change other about { - if (check.value) - return ((field.value*exces.value*15.0)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306006 - - hidden - - - - - 11 - - start - - - 106014 - - editable - - - idTrue: f.106014, - trans: t.421, - other: f.106015; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106014, - trans: t.421, - other: f.106015; - make other,required on trans when { idTrue.value } - - - idTrue: f.106014, - trans: t.421, - other: f.306007; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106014, - trans: t.421, - other: f.106015; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106014, - trans: t.421, - other: f.306007; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106014, - other: f.106015; - change other about { null; } - - - idTrue: f.106014, - other: f.306007; - change other about { null; } - - - - - - 12 - - start - - - 106015 - - hidden - - field: f.this, - check: f.106014, - exces: f.208002, - other: f.306007; - change other about { - if (check.value) - return ((field.value*exces.value*50.0)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306007 - - hidden - - - - - 13 - - start - - - 106016 - - editable - - - idTrue: f.106016, - trans: t.421, - other: f.106017; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106016, - trans: t.421, - other: f.106017; - make other,required on trans when { idTrue.value } - - - idTrue: f.106016, - trans: t.421, - other: f.306008; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106016, - trans: t.421, - other: f.106017; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106016, - trans: t.421, - other: f.306008; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106016, - other: f.106017; - change other about { null; } - - - idTrue: f.106016, - other: f.306008; - change other about { null; } - - - - - - 14 - - start - - - 106017 - - hidden - - field: f.this, - check: f.106016, - exces: f.208002, - other: f.306008; - change other about { - if (check.value) - return ((field.value*exces.value*3.5)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306008 - - hidden - - - - - 15 - - start - - - 106018 - - editable - - - idTrue: f.106018, - trans: t.421, - other: f.106019; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106018, - trans: t.421, - other: f.106019; - make other,required on trans when { idTrue.value } - - - idTrue: f.106018, - trans: t.421, - other: f.306009; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106018, - trans: t.421, - other: f.106019; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106018, - trans: t.421, - other: f.306009; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106018, - other: f.106019; - change other about { null; } - - - idTrue: f.106018, - other: f.306009; - change other about { null; } - - - - - - 16 - - start - - - 106019 - - hidden - - field: f.this, - check: f.106018, - exces: f.208002, - other: f.306009; - change other about { - if (check.value) - return ((field.value*exces.value*7.0)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306009 - - hidden - - - - - 17 - - start - - - 106020 - - editable - - - idTrue: f.106020, - trans: t.421, - other: f.106021; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106020, - trans: t.421, - other: f.106021; - make other,required on trans when { idTrue.value } - - - idTrue: f.106020, - trans: t.421, - other: f.306010; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106020, - trans: t.421, - other: f.106021; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106020, - trans: t.421, - other: f.306010; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106020, - other: f.106021; - change other about { null; } - - - idTrue: f.106020, - other: f.306010; - change other about { null; } - - - - - - 18 - - start - - - 106021 - - hidden - - field: f.this, - check: f.106020, - exces: f.208002, - other: f.306010; - change other about { - if (check.value) - return ((field.value*exces.value*10.0)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306010 - - hidden - - - - - 19 - - start - - - 106024 - - visible - - - - 106025 - - visible - - - - - - - 364 - 620 - 1020 - - 7 - auto - - 2 - - - 1 - - true - - - - 1 - Nehnuteľnosť - start - - - 105006 - - hidden - - - - - 105036 - - hidden - - - - - 305002 - - hidden - - - - - 308001 - - hidden - - - - - 2 - Domácnosť - start - - - 106002 - - hidden - - - - - 106022 - - hidden - - - - - 106023 - - hidden - - - - - 306001 - - hidden - - - - - 308002 - - hidden - - - - - 3 - Poistenie zodpovednosti - start - - - 308008 - - hidden - - - - - 308009 - - hidden - - - - - 308003 - - hidden - - - - - 4 - Sumarizácia poistnej sumy - start - true - - - 308004 - - visible - - - - - 5 - - start - true - - - 108001 - - editable - required - - - - - 2 - - start - true - - - 308005 - - visible - - - - - 2 - - start - true - - - 108002 - - editable - required - - - - - 2 - - start - true - - - 108005 - - hidden - - - - - 2 - - start - true - - - 108003 - - editable - - - - - 2 - - start - true - - - 108004 - - editable - - - - - 2 - - start - true - - - 308006 - - visible - - - - - 2 - - start - true - - - 308010 - - visible - - - - - 3 - start - false - - 309001 - - hidden - - - self: f.this; - generate "Insurance.offerId",once into self - - - - - - 309003 - - visible - - - - - - - 588 - 620 - 1180 - - 8 - auto - - 2 - - - 1 - - true - - - - - 1 - Poistník - start - - - - 109007 - - editable - - - - - 109058 - - hidden - - - - - 109012 - - hidden - - - - - 109061 - - hidden - - - - - 109062 - - hidden - - - - - 109008 - - editable - - - - - 109009 - - editable - - - - - 109010 - - editable - required - - - - - 109011 - - editable - required - - - - - 109016 - - editable - required - - - - - 109017 - - editable - required - - - - - 109013 - - editable - required - - - - - 109014 - - editable - required - - - - - 109015 - - editable - required - - - - - 109018 - - editable - - - - - 109019 - - editable - - - - - 2 - Poistený - - - 109020 - - editable - - - - - - 109021 - - hidden - - - - - 109059 - - hidden - - - - - 109026 - - hidden - - - - - 109063 - - hidden - - - - - 109064 - - hidden - - - - - 109022 - - hidden - - - - - 109023 - - hidden - - - - - 109024 - - hidden - - - - - 109025 - - hidden - - - - - 109030 - - hidden - - - - - 109031 - - hidden - - - - - 109027 - - hidden - - - - - 109028 - - hidden - - - - - 109029 - - hidden - - - - - 109032 - - hidden - - - - - 109033 - - hidden - - - - - 5 - Miesto poistenia - start - - - 109045 - - editable - required - - - - 109046 - - editable - required - - - - 109047 - - editable - required - - - - 109048 - - editable - required - - - - - 3 - Adresa trvalého pobytu - - - 109035 - - editable - - - - - 9 - - - 109036 - - hidden - - - - 109037 - - hidden - - - - 109038 - - hidden - - - - 109039 - - hidden - - - - - 4 - Korešpondenčná adresa - start - - - - 109034 - - editable - - - - - 7 - - start - - 109041 - - hidden - - - - 109042 - - hidden - - - - 109043 - - hidden - - - - 109044 - - hidden - - - - - 6 - Adresa garáže - - - 109054 - - hidden - - - - 109055 - - hidden - - - - 109056 - - hidden - - - - 109057 - - hidden - - - - - - - - - - 1618 - 1180 - 260 - - 9 - auto - - 3 - - - 1 - - true - - - - 1 - start - - - 309001 - - visible - - - - - 109001 - - editable - - - - - 109002 - - hidden - - - - - 109003 - - hidden - - - - 109004 - - editable - - - - - 109005 - - editable - - - - - 109060 - - editable - - - - - 109006 - - required - editable - - - - - 109065 - - hidden - - - - - 109066 - - editable - - - - - 109067 - - editable - - - - - 309004 - - visible - - - - - - - 1661 - 1185 - 898 - - 9 - auto - - 3 - - - 1 - - true - - - - 1 - start - - - 309001 - - visible - - - - - 109001 - - required - editable - - - - - 109002 - - hidden - - - - - 109003 - - hidden - - - - 109004 - - editable - - - - - 109005 - - editable - - - - - 109060 - - editable - - - - - 109006 - - required - editable - - - - - 109065 - - hidden - - - - - 109066 - - editable - - - - - 109067 - - editable - - - - - 309004 - - visible - - - - - - - 332 - 1180 - 580 - - 9 - auto - - 3 - - - 1 - - true - - - - 1 - start - - - 309001 - - visible - - - - - 109001 - - required - editable - - - - - 109002 - - hidden - - - - - 109003 - - hidden - - - - 109004 - - editable - - - - - 109005 - - editable - - - - - 109060 - - editable - - - - - 109006 - - required - editable - - - - - 109065 - - hidden - - - - - 109066 - - editable - - - - - 109067 - - editable - - - - - 309004 - - visible - - - - - - - - - - 674 - 1433 - 965 - - 11 - - 3 - - - - - 687 - 1431 - 1243 - - 12 - - 3 - - - - - - - - 680 - 1681 - 967 - - 12 - - 3 - - - 2 - - true - - - - 1 - Informačné údaje - start - - - - 309001 - - forbidden - immediate - - - - - 109010 - - visible - immediate - - - - - 109011 - - visible - immediate - - - - - 109001 - - visible - immediate - - - - - - 2 - Údaje o platbe - start - - - 110001 - - editable - - - - - 110002 - - editable - - - - - 110003 - - required - editable - - - - - 110004 - - editable - - - - - 110005 - - editable - - - - - 110006 - - editable - - - - - 110007 - - editable - - - - - 110008 - - required - editable - - - - - 110009 - - required - editable - - - - - 110010 - - editable - - - - - 110011 - - required - editable - - - - - 110012 - - editable - - - - - 110013 - - editable - - - - - 110014 - - editable - - - - - 110015 - - editable - - - - - 110016 - - editable - - - - - 110017 - - editable - - - - - 110018 - - editable - - - - - 110019 - - editable - - - - - 110020 - - editable - - - - - 110021 - - editable - - - - - 110022 - - editable - - - - - 110023 - - editable - - - - - 110024 - - editable - - - - - 110025 - - editable - - - - - 110026 - - editable - - - - - - - 686 - 1870 - 1071 - - 13 - - 3 - - - - - 692 - 1682 - 1250 - - 14 - - 3 - - - - - 694 - 2077 - 1245 - - 15 - - 3 - - - - - - - - 2015 - 2229 - 38 - - 1 - - 3 - - - 1 - - true - - - - 1 - - start - - - 301005 - - visible - - - - - 101001 - - visible - - - - - 301002 - - visible - - - - 101002 - - visible - - - - - 2 - - start - true - - - 101003 - - visible - - - - - 3 - - true - - - 101004 - - visible - - - - - 4 - - true - - - 101005 - - visible - - - - - 101006 - - visible - - - - - 101007 - - visible - - - - - 101008 - - visible - - - - - 101008 - - visible - - - - - 8 - - true - - - 101012 - - visible - - - - - 101014 - - visible - - - - - 101016 - - visible - - - - - - - 2019 - 2231 - 143 - - 2 - - 3 - - - 1 - - true - - - - 2 - - start - - - 102001 - - visible - - - - - 105001 - - visible - - - - - 105002 - - visible - - - - - 105003 - - visible - - - - - 105004 - - visible - - - - - 305001 - - visible - - - - - 102002 - - visible - - - - - 102003 - - visible - - - - - 102004 - - visible - - - - - 102006 - - visible - - - - - 102007 - - visible - - - - - 3 - - left - - - 107001 - - visible - - - - - - - 2020 - 2233 - 247 - - 3 - - 3 - - - 1 - - true - - - - 1 - - - - 105031 - - visible - - - - - 105032 - - visible - - - - - 305015 - - visible - - - - - 105033 - - visible - - - - - 105034 - - visible - - - - - 305016 - - visible - - - - - - - 2021 - 2233 - 351 - - 4 - - 3 - - - 1 - - true - - - - 1 - - - - 105035 - - visible - - - - - 105007 - - visible - - - - - 105008 - - visible - - - - - 305019 - - visible - - - - - 305003 - - visible - - - - - 105009 - - visible - - - - - 105010 - - visible - - - - - 305004 - - visible - - - - - 105011 - - visible - - - - - 105012 - - visible - - - - - 305005 - - visible - - - - - 105013 - - visible - - - - - 105014 - - visible - - - - - 305006 - - visible - - - - - 105015 - - visible - - - - - 105016 - - visible - - - - - 305007 - - visible - - - - - 105017 - - visible - - - - - 105018 - - visible - - - - - 305008 - - visible - - - - - 105019 - - visible - - - - - 105020 - - visible - - - - - 305009 - - visible - - - - - 105021 - - visible - - - - - 105022 - - visible - - - - - 305010 - - visible - - - - - 105023 - - visible - - - - - 105024 - - visible - - - - - 305011 - - visible - - - - - 105025 - - visible - - - - - 105026 - - visible - - - - - 305012 - - visible - - - - - 105027 - - visible - - - - - 105028 - - visible - - - - - 305013 - - visible - - - - - 105029 - - visible - - - - - 105030 - - visible - - - - - 305014 - - visible - - - - - 2 - - - - 305017 - - visible - - - - - 305018 - - visible - - - - - - - 2018 - 2231 - 451 - - 5 - - 3 - - - 1 - - true - - - - 1 - - - - 103001 - - visible - - - - - 106003 - - visible - - - - - 103002 - - visible - - - - - 103004 - - visible - - - - - 103005 - - visible - - - - - - - 2729 - 2227 - 1021 - - 7 - - 2 - - - 1 - - true - - - - 1 - Nehnuteľnosť - start - - - 105006 - - visible - - - - - 105036 - - visible - - - - - 305002 - - visible - - - - - 308001 - - visible - - - - - 2 - Domácnosť - start - - - 106002 - - visible - - - - - 106022 - - visible - - - - - 106023 - - visible - - - - - 306001 - - visible - - - - - 308002 - - visible - - - - - 3 - Poistenie zodpovednosti - start - - - 308008 - - visible - - - - - 308009 - - visible - - - - - 308003 - - visible - - - - - 4 - Sumarizácia poistnej sumy - start - true - - - 308004 - - visible - - - - - 5 - - start - true - - - 108001 - - visible - - - - - 2 - - start - true - - - 308005 - - visible - - - - - 2 - - start - true - - - 108002 - - visible - - - - - 2 - - start - true - - - 108005 - - visible - - - - - 2 - - start - true - - - 108003 - - visible - - - - - 2 - - start - true - - - 108004 - - visible - - - - - 2 - - start - true - - - 308006 - - visible - - - - - 2 - - start - true - - - 308010 - - visible - - - - - 3 - start - false - - 309001 - - visible - - - self: f.this; - generate "Insurance.offerId",once into self - - - - - - 309003 - - visible - - - - - - - 2017 - 2233 - 549 - - 6 - - 3 - - - 1 - - true - - - - 1 - - - - 106004 - - visible - - - - - 106005 - - visible - - - - - 306002 - - visible - - - - - 106006 - - visible - - - - - 106007 - - visible - - - - - 306003 - - visible - - - - - 106008 - - visible - - - - - 106009 - - visible - - - - - 306004 - - visible - - - - - 106010 - - visible - - - - - 106011 - - visible - - - - - 306005 - - visible - - - - - 106012 - - visible - - - - - 106013 - - visible - - - - - 306006 - - visible - - - - - 106014 - - visible - - - - - 106015 - - visible - - - - - 306007 - - visible - - - - - 106016 - - visible - - - - - 106017 - - visible - - - - - 306008 - - visible - - - - - 106018 - - visible - - - - - 106019 - - visible - - - - - 306009 - - visible - - - - - 106020 - - visible - - - - - 106021 - - visible - - - - - 306010 - - visible - - - - - - - 2016 - 2235 - 646 - - 7 - - 3 - - - 1 - - true - - - - 1 - - - - - 109007 - - visible - - - - - 109008 - - visible - - - - - 109009 - - visible - - - - - 109010 - - visible - - - - - 109011 - - visible - - - - - 109012 - - visible - - - - - 109013 - - visible - - - - - 109014 - - visible - - - - - 109015 - - visible - - - - - 109016 - - visible - - - - - 109017 - - visible - - - - - 109018 - - visible - - - - - 109019 - - visible - - - - - 109020 - - visible - - - - - - 109021 - - hidden - - - - - 109022 - - hidden - - - - - 109023 - - hidden - - - - - 109024 - - hidden - - - - - 109025 - - hidden - - - - - 109026 - - hidden - - - - - 109027 - - hidden - - - - - 109028 - - hidden - - - - - 109029 - - hidden - - - - - 109030 - - hidden - - - - - 109031 - - hidden - - - - - 109032 - - hidden - - - - - 109033 - - hidden - - - - - - 109036 - - - visible - - - - 109037 - - - visible - - - - 109038 - - - visible - - - - 109039 - - - visible - - - - - 109041 - - visible - - - - 109042 - - visible - - - - 109043 - - visible - - - - 109044 - - visible - - - - - 109045 - - - visible - - - - 109046 - - - visible - - - - 109047 - - - visible - - - - 109048 - - - visible - - - - - 109054 - - - visible - - - - 109055 - - - visible - - - - 109056 - - - visible - - - - 109057 - - - visible - - - - - - - 2014 - 2237 - 743 - - 8 - - 3 - - - 1 - - true - - - - 1 - - - - 309001 - - visible - - - - - 109001 - - visible - - - - - 109002 - - visible - - - - - 109003 - - visible - - - - 109004 - - visible - - - - - 109005 - - visible - - - - - 109006 - - visible - - - - - 309004 - - visible - - - - - - - 2045 - 2237 - 841 - - 9 - - 3 - - - 1 - - true - - - - 1 - - - - 308007 - - visible - - - - - - - 2046 - 2237 - 929 - - 10 - - 3 - - - 1 - - true - - - - - - 2484 - 1457 - 117 - - - - 1 - - - 410001 - - hidden - - - self: f.this; - generate "Insurance.sendMail",always into self - - - - - - - - - 1 - 20 - 580 - - 1 - false - - - 398 - 420 - 60 - - 0 - false - - - 399 - 420 - 220 - - 0 - false - - - 400 - 420 - 700 - - 0 - false - - - 402 - 420 - 1020 - - 0 - false - - - 415 - 420 - 540 - - 0 - false - - - 416 - 420 - 380 - - 0 - false - - - 422 - 420 - 860 - - 0 - false - - - 444 - 860 - 60 - - 0 - false - - - 445 - 860 - 220 - - 0 - false - - - 446 - 900 - 700 - - 0 - false - - - 589 - 420 - 1180 - - 0 - false - - - 594 - 900 - 1180 - - 0 - false - - - 633 - 260 - 60 - - 0 - false - - - 672 - 1530 - 585 - - 0 - false - - - 682 - 1681 - 1070 - - 0 - false - - - 683 - 1430 - 1071 - - 0 - false - - - 693 - 1862 - 1249 - - 0 - false - - - 1368 - 900 - 380 - - 0 - false - - - 1369 - 900 - 540 - - 0 - false - - - 1372 - 900 - 860 - - 0 - false - - - 1393 - 900 - 1020 - - 0 - false - - - 1601 - 540 - 300 - - 0 - false - - - 1607 - 540 - 460 - - 0 - false - - - 1612 - 540 - 140 - - 0 - false - - - 1626 - 540 - 620 - - 0 - false - - - 1668 - 180 - 140 - - 0 - false - - - 1673 - 540 - 940 - - 0 - false - - - 1677 - 540 - 780 - - 0 - false - - - 1689 - 540 - 1100 - - 0 - false - - - 1851 - 180 - 1180 - - 0 - false - - - 2047 - 2063 - 43 - - 0 - false - - - 2048 - 2069 - 146 - - 0 - false - - - 2049 - 2069 - 250 - - 0 - false - - - 2050 - 2071 - 350 - - 0 - false - - - 2051 - 2065 - 450 - - 0 - false - - - 2052 - 2069 - 554 - - 0 - false - - - 2053 - 2071 - 651 - - 0 - false - - - 2054 - 2073 - 746 - - 0 - false - - - 2055 - 2073 - 837 - - 0 - false - - - 2056 - 2070 - 927 - - 0 - false - - - 2280 - 715 - 615 - - 0 - false - - - 2284 - 782 - 931 - - 0 - false - - - 2480 - 1399 - 117 - - 0 - false - - - 2728 - 2067 - 1013 - - 0 - false - - - - 7 - regular - 1 - 2 - 1 - - - 9 - regular - 1 - 3 - 1 - - - 12 - regular - 1 - 4 - 1 - - - 403 - regular - 398 - 154 - 1 - - - 404 - regular - 154 - 398 - 1 - - - 405 - regular - 399 - 155 - 1 - - - 406 - regular - 155 - 399 - 1 - - - 407 - regular - 400 - 363 - 1 - - - 408 - regular - 363 - 400 - 1 - - - 411 - regular - 402 - 364 - 1 - - - 412 - regular - 364 - 402 - 1 - - - 417 - regular - 415 - 413 - 1 - - - 418 - regular - 413 - 415 - 1 - - - 419 - regular - 416 - 414 - 1 - - - 420 - regular - 414 - 416 - 1 - - - 423 - regular - 422 - 421 - 1 - - - 424 - regular - 421 - 422 - 1 - - - 425 - regular - 2 - 398 - 1 - - - 426 - regular - 3 - 398 - 1 - - - 427 - regular - 4 - 398 - 1 - - - 428 - regular - 2 - 399 - 1 - - - 429 - regular - 3 - 399 - 1 - - - 430 - regular - 3 - 400 - 1 - - - 431 - regular - 4 - 400 - 1 - - - 435 - regular - 3 - 402 - 1 - - - 436 - regular - 4 - 402 - 1 - - - 437 - regular - 2 - 402 - 1 - - - 439 - regular - 3 - 415 - 1 - - - 441 - regular - 3 - 416 - 1 - - - 442 - regular - 4 - 422 - 1 - - - 443 - regular - 3 - 422 - 1 - - - 452 - regular - 154 - 444 - 1 - - - 453 - regular - 155 - 445 - 1 - - - 454 - regular - 363 - 446 - 1 - - - 514 - regular - 402 - 332 - 1 - - - 516 - regular - 400 - 332 - 1 - - - 517 - regular - 422 - 332 - 1 - - - 535 - regular - 446 - 332 - 1 - - - 591 - regular - 589 - 588 - 1 - - - 592 - regular - 588 - 589 - 1 - - - 595 - regular - 588 - 594 - 1 - - - 634 - regular - 2 - 633 - 1 - - - 677 - regular - 672 - 674 - 1 - - - 681 - regular - 672 - 680 - 1 - - - 684 - regular - 674 - 683 - 1 - - - 685 - regular - 680 - 682 - 1 - - - 688 - regular - 683 - 687 - 1 - - - 689 - regular - 687 - 683 - 1 - - - 690 - regular - 682 - 686 - 1 - - - 691 - regular - 686 - 682 - 1 - - - 695 - regular - 682 - 692 - 1 - - - 696 - regular - 692 - 693 - 1 - - - 697 - regular - 693 - 694 - 1 - - - 698 - regular - 694 - 693 - 1 - - - 1373 - regular - 414 - 1368 - 1 - - - 1374 - regular - 413 - 1369 - 1 - - - 1394 - regular - 364 - 1393 - 1 - - - 1397 - regular - 421 - 1372 - 1 - - - 1400 - regular - 1372 - 332 - 1 - - - 1595 - regular - 445 - 332 - 1 - - - 1596 - reset - 445 - 155 - 1 - - - 1599 - reset - 1368 - 414 - 1 - - - 1600 - reset - 1369 - 413 - 1 - - - 1602 - regular - 155 - 1601 - 1 - - - 1603 - regular - 1601 - 414 - 1 - - - 1604 - regular - 414 - 1601 - 1 - - - 1605 - regular - 2 - 416 - 1 - - - 1606 - regular - 2 - 415 - 1 - - - 1608 - regular - 414 - 1607 - 1 - - - 1609 - regular - 1607 - 413 - 1 - - - 1610 - regular - 413 - 1607 - 1 - - - 1611 - regular - 444 - 332 - 1 - - - 1613 - regular - 154 - 1612 - 1 - - - 1614 - regular - 1612 - 155 - 1 - - - 1615 - regular - 155 - 1612 - 1 - - - 1616 - regular - 1368 - 332 - 1 - - - 1617 - regular - 1369 - 332 - 1 - - - 1619 - regular - 444 - 1618 - 1 - - - 1620 - regular - 445 - 1618 - 1 - - - 1621 - regular - 1368 - 1618 - 1 - - - 1622 - regular - 1369 - 1618 - 1 - - - 1623 - regular - 1393 - 1618 - 1 - - - 1625 - regular - 594 - 1618 - 1 - - - 1627 - regular - 413 - 1626 - 1 - - - 1630 - reset - 444 - 154 - 1 - - - 1640 - regular - 2 - 589 - 1 - - - 1641 - regular - 398 - 1618 - 1 - - - 1642 - regular - 399 - 1618 - 1 - - - 1643 - regular - 416 - 1618 - 1 - - - 1644 - regular - 415 - 1618 - 1 - - - 1645 - regular - 633 - 1618 - 1 - - - 1646 - regular - 402 - 1618 - 1 - - - 1648 - regular - 589 - 1618 - 1 - - - 1649 - reset - 1393 - 364 - 1 - - - 1651 - reset - 594 - 588 - 1 - - - 1657 - regular - 332 - 672 - 1 - - - 1660 - regular - 1618 - 672 - 1 - - - 1662 - regular - 3 - 589 - 1 - - - 1669 - regular - 3 - 1668 - 1 - - - 1670 - regular - 2 - 1668 - 1 - - - 1671 - regular - 1668 - 155 - 1 - - - 1672 - regular - 155 - 1668 - 1 - - - 1674 - regular - 2 - 1673 - 1 - - - 1675 - regular - 1673 - 364 - 1 - - - 1676 - regular - 364 - 1673 - 1 - - - 1678 - regular - 363 - 1677 - 1 - - - 1679 - regular - 1677 - 421 - 1 - - - 1680 - regular - 421 - 1677 - 1 - - - 1685 - regular - 421 - 1673 - 1 - - - 1686 - regular - 1626 - 363 - 1 - - - 1687 - regular - 363 - 1626 - 1 - - - 1688 - regular - 4 - 1626 - 1 - - - 1690 - regular - 364 - 1689 - 1 - - - 1691 - regular - 1689 - 588 - 1 - - - 1692 - regular - 588 - 1689 - 1 - - - 1693 - regular - 1393 - 332 - 1 - - - 1694 - regular - 594 - 332 - 1 - - - 1696 - reset - 446 - 363 - 1 - - - 1697 - reset - 1372 - 421 - 1 - - - 1698 - regular - 589 - 332 - 1 - - - 1702 - regular - 4 - 589 - 1 - - - 1704 - regular - 444 - 1661 - 1 - - - 1705 - regular - 446 - 1661 - 1 - - - 1706 - regular - 1372 - 1661 - 1 - - - 1707 - regular - 1393 - 1661 - 1 - - - 1708 - regular - 594 - 1661 - 1 - - - 1710 - regular - 398 - 1661 - 1 - - - 1711 - regular - 400 - 1661 - 1 - - - 1712 - regular - 422 - 1661 - 1 - - - 1713 - regular - 402 - 1661 - 1 - - - 1714 - regular - 589 - 1661 - 1 - - - 1716 - regular - 1661 - 672 - 1 - - - 1852 - regular - 4 - 1851 - 1 - - - 1853 - regular - 1851 - 1661 - 1 - - - 2010 - regular - 398 - 332 - 1 - - - 2011 - regular - 399 - 332 - 1 - - - 2012 - regular - 416 - 332 - 1 - - - 2013 - regular - 415 - 332 - 1 - - - 2057 - regular - 1618 - 2047 - 1 - - - 2058 - regular - 1618 - 2048 - 1 - - - 2059 - regular - 1618 - 2049 - 1 - - - 2060 - regular - 1618 - 2050 - 1 - - - 2061 - regular - 1618 - 2051 - 1 - - - 2062 - regular - 1618 - 2052 - 1 - - - 2063 - regular - 1618 - 2053 - 1 - - - 2064 - regular - 1618 - 2054 - 1 - - - 2065 - regular - 1618 - 2055 - 1 - - - 2066 - regular - 1618 - 2056 - 1 - - - 2067 - regular - 1661 - 2056 - 1 - - - 2068 - regular - 1661 - 2055 - 1 - - - 2069 - regular - 1661 - 2054 - 1 - - - 2070 - regular - 1661 - 2053 - 1 - - - 2071 - regular - 1661 - 2052 - 1 - - - 2072 - regular - 1661 - 2051 - 1 - - - 2073 - regular - 1661 - 2050 - 1 - - - 2074 - regular - 1661 - 2049 - 1 - - - 2075 - regular - 1661 - 2048 - 1 - - - 2076 - regular - 1661 - 2047 - 1 - - - 2077 - regular - 2047 - 2015 - 1 - - - 2078 - regular - 2015 - 2047 - 1 - - - 2079 - regular - 2048 - 2019 - 1 - - - 2080 - regular - 2019 - 2048 - 1 - - - 2081 - regular - 2049 - 2020 - 1 - - - 2082 - regular - 2020 - 2049 - 1 - - - 2083 - regular - 2050 - 2021 - 1 - - - 2084 - regular - 2021 - 2050 - 1 - - - 2085 - regular - 2051 - 2018 - 1 - - - 2086 - regular - 2018 - 2051 - 1 - - - 2087 - regular - 2052 - 2017 - 1 - - - 2088 - regular - 2017 - 2052 - 1 - - - 2089 - regular - 2053 - 2016 - 1 - - - 2090 - regular - 2016 - 2053 - 1 - - - 2091 - regular - 2054 - 2014 - 1 - - - 2092 - regular - 2014 - 2054 - 1 - - - 2093 - regular - 2055 - 2045 - 1 - - - 2094 - regular - 2045 - 2055 - 1 - - - 2095 - regular - 2056 - 2046 - 1 - - - 2096 - regular - 2046 - 2056 - 1 - - - 2097 - regular - 332 - 2047 - 1 - - - 2098 - regular - 332 - 2048 - 1 - - - 2099 - regular - 332 - 2049 - 1 - - - 2100 - regular - 332 - 2050 - 1 - - - 2101 - regular - 332 - 2051 - 1 - - - 2102 - regular - 332 - 2052 - 1 - - - 2103 - regular - 332 - 2053 - 1 - - - 2104 - regular - 332 - 2054 - 1 - - - 2105 - regular - 332 - 2055 - 1 - - - 2106 - regular - 332 - 2056 - 1 - - - 2281 - regular - 154 - 2280 - 1 - - - 2282 - regular - 2280 - 363 - 1 - - - 2283 - regular - 363 - 2280 - 1 - - - 2285 - regular - 413 - 2284 - 1 - - - 2286 - regular - 2284 - 364 - 1 - - - 2287 - regular - 364 - 2284 - 1 - - - 2479 - regular - 363 - 2284 - 1 - - - 2481 - regular - 1618 - 2480 - 1 - - - 2482 - regular - 332 - 2480 - 1 - - - 2483 - regular - 1661 - 2480 - 1 - - - 2485 - regular - 2480 - 2484 - 1 - - - 2730 - regular - 2728 - 2729 - 1 - - - 2731 - regular - 2729 - 2728 - 1 - - - 2732 - regular - 1618 - 2728 - 1 - - - 2733 - regular - 332 - 2728 - 1 - - - 2734 - regular - 1661 - 2728 - 1 - - \ No newline at end of file diff --git a/src/main/resources/petriNets/insurance_role_test.xml b/src/main/resources/petriNets/insurance_role_test.xml deleted file mode 100644 index ef4cd543430..00000000000 --- a/src/main/resources/petriNets/insurance_role_test.xml +++ /dev/null @@ -1,14519 +0,0 @@ - - - false - - - - - 1 - Výber poistenia - - - 2 - Výpočet poistenia - - - 3 - Zmluva - - - - 1 - Agent - - - 2 - Company - - - 3 - Admin - - - - - 301001 - - - - Obec - 301001 - Názov - - - 301005 - Obec - - - - field: f.301002, - zipcode: f.101001, - obec: f.this; - change field about { - return "L3" as String; - } - - - - - - field: f.this, - other: f.109048; - change other about { - return field?.value?.defaultValue; - } - - - - - PSČ - 101001 - PSČ - - - - field: f.this, - other: f.109047; - change other about { - return field.value; - } - - - - - 301006 - PSČ - - - - Lokalita - 301002 - Typ - - - field: f.this, - coeff: f.201001; - change coeff about { - if (field.value=="L5") - return 3.8 as Double; - if (field.value=="L4") - return 3.4 as Double; - if (field.value=="L3") - return 3.2 as Double; - if (field.value=="L2") - return 3.0 as Double; - if (field.value=="L1") - return 2.8 as Double; - - } - - - - - field: f.this, - coeff: f.201018; - change coeff about { - if (field.value=="L5") - return 3.8 as Double; - if (field.value=="L4") - return 3.4 as Double; - if (field.value=="L3") - return 3.2 as Double; - if (field.value=="L2") - return 3.0 as Double; - if (field.value=="L1") - return 2.8 as Double; - } - - - - - Nachádza sa miesto poistenia mimo obce (extravilán)? - 101002 - - - field: f.this, - coeff: f.201002; - change coeff about { - if (field.value) - return 1.2 as Double; - return 1.0 as Double; - } - - - - - Bolo miesto poistenia postihnuté povodňou alebo záplavou za posledných 10 rokov? - 101003 - - - field: f.this, - coeff: f.201003; - change coeff about { - if (field.value) - return 1.5 as Double; - return 1.0 as Double; - } - - - - - Nachádza sa miesto poistenia vo vzdialenosti kratšej ako 300 m od vodného toku? - 101004 - - - field: f.this, - coeff: f.201004; - change coeff about { - if (field.value) - return 1.3 as Double; - return 1.0 as Double; - } - - - - - 101005 - Koľko rokov žijete v poisťovanej nehnuteľnosti? - Počet rokov - menej ako 1 - 1 až 5 - 6 až 10 - viac ako 10 - 6 až 10 - - - field: f.this, - coeff: f.201005; - change coeff about { - if (field.value=="menej ako 1") - return 1.0 as Double; - if (field.value=="1 až 5") - return 1.0 as Double; - if (field.value=="6 až 10") - return 1.0 as Double; - if (field.value=="viac ako 10") - return 1.0 as Double; - } - - - - - Aký je vzťah poisteného k poisťovanej nehnuteľnosti? - 101006 - Vzťah - vlastník nehnuteľnosti - vlastník ma hypotéku na nehnuteľnosť - poistený je v prenájme - iné - vlastník nehnuteľnosti - - - field: f.this, - coeff: f.201006; - change coeff about { - if (field.value=="vlastník nehnuteľnosti") - return 1.0 as Double; - if (field.value=="vlastník má úver alebo hypotéku na nehnuteľnosť") - return 1.0 as Double; - if (field.value=="poistený je v prenájme") - return 1.1 as Double; - if (field.value=="iné") - return 1.1 as Double; - } - - - - - Koľko dospelých žije v domácnosti? - 101007 - Počet - 1 - 2 - 3 - viac ako 3 - 2 - - - field: f.this, - coeff: f.201007; - change coeff about { - if (field.value=="1") - return 0.95 as Double; - if (field.value=="2") - return 1.0 as Double; - if (field.value=="3") - return 1.05 as Double; - if (field.value=="viac ako 3") - return 1.1 as Double; - } - - - - - Koľko detí žije v domácnosti? - 101008 - Počet - 0 - 1 - 2 - viac ako 2 - 1 - - - field: f.this, - coeff: f.201008; - change coeff about { - if (field.value=="0") - return 1.0 as Double; - if (field.value=="1") - return 1.0 as Double; - if (field.value=="2") - return 1.05 as Double; - if (field.value=="viac ako 2") - return 1.1 as Double; - } - - - - - Žije v poisťovanej domácnosti pes alebo mačka? - 101012 - - - field: f.this, - coeff: f.201012; - change coeff about { - if (field.value) - return 1.05 as Double; - return 1.0 as Double; - } - - - - - Je nehnuteľnosť využívaná aj na podnikanie? - 101014 - - - field: f.this, - coeff: f.201014; - change coeff about { - if (field.value) - return 1.1 as Double; - return 1.0 as Double; - } - - - - - Počet poistných udalostí za posledné 3 roky? - 101016 - Počet - 0 - 1 - 2 a viac - 0 - - - field: f.this, - coeff: f.201016; - change coeff about{ - if (field.value=="0") - return 1.0 as Double; - if (field.value=="1") - return 1.1 as Double; - if (field.value=="2 a viac") - return 1.2 as Double; - } - - - - - - Poistenie nehnuteľnosti - 105005 - Spoluúčasť - 0.00 € - 50.00 € - 150.00 € - 50.00 € - - - field: f.this, - coeff: f.208001; - change coeff about { - if (field.value=="0.00 €") - return 1.1 as Double; - if (field.value=="50.00 €") - return 1.0 as Double; - if (field.value=="150.00 €") - return 0.9 as Double; - } - - - - - Predmet poistenia - 102001 - Typ - byt - rodinný dom - chata - bungalow - - - field: f.this, - coeff: f.202001; - change coeff about { - if (field.value=="byt") - return 1.0 as Double; - if (field.value=="rodinný dom") - return 1.0 as Double; - if (field.value=="chata") - return 1.1 as Double; - if (field.value=="bungalow") - return 1.0 as Double; - if (field.value=="rozostavaná stavba") - return 1.0 as Double; - } - - - - - field: f.this, - coeff: f.201019; - change coeff about { - if (field.value=="byt") - return 0.9 as Double; - if (field.value=="rodinný dom") - return 0.9 as Double; - if (field.value=="chata") - return 1.2 as Double; - if (field.value=="bungalow") - return 0.9 as Double; - if (field.value=="rozostavaná stavba") - return 1.2 as Double; - } - - - - - field: f.this, - coeff: f.103001; - change coeff about { - if (field.value=="byt") - return "byt"; - if (field.value=="rodinný dom") - return "rodinný dom"; - if (field.value=="chata") - return "chata"; - if (field.value=="bungalow") - return "bungalow"; - } - - - - - field: f.this, - coeff: f.102003; - change coeff about { - if (field.value=="byt") - return "škridla"; - } - - - - field: f.102001, - hide: f.103001, - trans: t.363; - make hide,visible on trans when { field.value != null } - - - field: f.102001, - hide: f.105001, - trans: t.155; - make hide,hidden on trans when { field.value=="byt"; } - - - field: f.102001, - hide: f.105002, - trans: t.155; - make hide,hidden on trans when { field.value=="byt"; } - - - field: f.102001, - hide: f.105003, - trans: t.155; - make hide,hidden on trans when { field.value=="byt"; } - - - field: f.102001, - hide: f.305001, - trans: t.155; - make hide,editable on trans when { field.value=="byt"; } - - - field: f.102001, - hide: f.305001, - trans: t.155; - make hide,required on trans when { field.value=="byt"; } - - - field: f.102001, - hide: f.102003, - trans: t.155; - make hide,hidden on trans when { field.value=="byt"; } - - - - field: f.102001, - hide: f.105001, - trans: t.155; - make hide,editable on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.102003, - trans: t.155; - make hide,editable on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.105001, - trans: t.155; - make hide,required on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.105002, - trans: t.155; - make hide,editable on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.105002, - trans: t.155; - make hide,required on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.105003, - trans: t.155; - make hide,editable on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.105003, - trans: t.155; - make hide,required on trans when { field.value!="byt"; } - - - field: f.102001, - hide: f.305001, - trans: t.155; - make hide,visible on trans when { field.value!="byt"; } - - - - p1: f.105001, - p2: f.105002, - p3: f.105003, - field: f.305001; - change field about { - return p1.value+p2.value+p3.value as Double; - } - - - - - Konštrukcia múrov - 102002 - Typ - tehla a/alebo betón - porobetón (ytong) - škvarobatón - sklo - drevo - tehla a/alebo betón - - - field: f.this, - coeff: f.202002; - change coeff about { - if (field.value=="tehla a/alebo betón") - return 1.0 as Double; - if (field.value=="porobetón (ytong)") - return 1.05 as Double; - if (field.value=="škvarobatón") - return 1.05 as Double; - if (field.value=="sklo") - return 1.3 as Double; - if (field.value=="drevo") - return 1.5 as Double; - } - - - - - Konštrukcia strechy - 102003 - Typ - škridla - plech - asfalt - sklo - šindel - iné - škridla - - - field: f.this, - coeff: f.202003; - change coeff about { - if (field.value=="škridla") - return 1.0 as Double; - if (field.value=="plech") - return 1.05 as Double; - if (field.value=="asfalt") - return 1.1 as Double; - if (field.value=="sklo") - return 1.15 as Double; - if (field.value=="šindel") - return 1.05 as Double; - if (field.value=="iné") - return 1.1 as Double; - } - - - - - Koľko rokov má nehnuteľnosť? - 102004 - Typ - menej ako 5 - 6 až 10 - 11 až 20 - viac ako 20 - 6 až 10 - - - field: f.this, - coeff: f.202004; - change coeff about { - if (field.value=="menej ako 5") - return 1.0 as Double; - if (field.value=="6 až 10") - return 1.02 as Double; - if (field.value=="11 až 20") - return 1.04 as Double; - if (field.value=="viac ako 20") - return 1.06 as Double; - } - - - - - Koľko izieb má nehnuteľnosť? - 102006 - Počet - 1 - 2 - 3 - 4 - viac ako 4 - - - field: f.this, - coeff: f.202006; - change coeff about { - if (field.value=="1") - return 0.9 as Double; - if (field.value=="2") - return 0.95 as Double; - if (field.value=="3") - return 1.0 as Double; - if (field.value=="4") - return 1.02 as Double; - if (field.value=="viac ako 4") - return 1.05 as Double; - } - - - - - check: f.this, - trans: t.364, - other: f.105006; - make other,visible on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.105036; - make other,editable on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.105036; - make other,required on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.305002; - make other,visible on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.308001; - make other,visible on trans when { check.value != null } - - - - - Koľko kúpeľní má nehnuteľnosť? - 102007 - Počet - 1 - 2 - viac ako 2 - - - field: f.this, - coeff: f.202007; - change coeff about { - if (field.value=="1") - return 1.0 as Double; - if (field.value=="2") - return 1.02 as Double; - if (field.value=="viac ako 2") - return 1.03 as Double; - } - - - - - - Umiestnenie domácnosti - 103001 - Typ - byt - rodinný dom - chata - bungalow - - - field: f.this, - coeff: f.203001; - change coeff about { - if (field.value=="byt") - return 1.0 as Double; - if (field.value=="rodinný dom") - return 1.0 as Double; - if (field.value=="chata") - return 1.25 as Double; - if (field.value=="bungalow") - return 1.0 as Double; - } - - - - - check: f.this, - trans: t.364, - other: f.106002; - make other,visible on trans when { true } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,editable on trans when { true } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,required on trans when { true } - - - - - check: f.this, - trans: t.364, - other: f.306001; - make other,visible on trans when { true } - - - - - check: f.this, - trans: t.364, - other: f.308002; - make other,visible on trans when { true } - - - - - Obývanosť domácnosti - 103002 - trvalá - dočasná - trvalá - - - field: f.this, - coeff: f.203002; - change coeff about { - if (field.value=="trvalá") - return 1.0 as Double; - if (field.value=="dočasná") - return 2.0 as Double; - } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,required on trans when { check.value=="trvalá" } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,editable on trans when { check.value=="trvalá" } - - - - - check: f.this, - trans: t.364, - other: f.106023; - make other,hidden on trans when { check.value=="trvalá" } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,hidden on trans when { check.value=="dočasná" } - - - - - check: f.this, - trans: t.364, - other: f.106023; - make other,required on trans when { check.value=="dočasná" } - - - - - check: f.this, - trans: t.364, - other: f.106023; - make other,editable on trans when { check.value=="dočasná" } - - - - - field: f.106002, - check: f.103002, - other: f.106022; - change other about { - if (check.value=="trvalá") - return field.value as Double; - return 1.0 as Double; - } - - - - - field: f.106002, - check: f.103002, - other: f.106023; - change other about { - if(check.value=="dočasná") - return field.value as Double; - return 1.0 as Double; - } - - - - - field: f.106023, - field2: f.106022, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field.value*field2.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - Je domácnosť zabezpečená funkčným alarmom? - 103004 - false - - - field: f.this, - coeff: f.203004; - change coeff about { - if (field.value) - return 0.97 as Double; - return 1.0 as Double; - } - - - - - field: f.this, - check: f.108005; - change check about { - return field.value; - } - - - - - Má domácnosť na oknách vo výške do 3 metrov od okolitého terénu mreže alebo vonkajšie žalúzie alebo - rolety? - - 103005 - false - - - field: f.this, - coeff: f.203005; - change coeff about { - if (field.value) - return 0.97 as Double; - return 1.0 as Double; - } - - - - - - Územná platnosť poistenia - 104003 - Slovenská republika - Európa - - - field: f.this, - coeff1: f.204002, - coeff: f.204003; - change coeff about { - if (field.value=="Slovenská republika") - return 1.0*coeff1.value as Double; - if (field.value=="Európa") - return 1.2*coeff1.value as Double; - } - - - - - field: f.107003, - coeff: f.204003, - excess: f.208002, - sum: f.308009; - change sum about { - def n = field.value.getDefaultValue().replaceAll("[,€ ]","") as Double; - return ((n*coeff.value*excess.value)/1000.0) as Double; - } - - - - - - Podlahová plocha pivnice - 105001 - m2 - 0 - inrange 0,1000 - - - - field: f.this, - location: f.301002, - coeff: f.205002; - change coeff about { - if (location.value=="L5") - return 850*field.value as Double; - if (location.value=="L4") - return 700*field.value as Double; - if (location.value=="L1") - return 400*field.value as Double; - if (location.value=="L2") - return 500*field.value as Double; - if (location.value=="L3") - return 650*field.value as Double; - } - - - - - p1: f.105001, - p2: f.105002, - p3: f.105003, - field: f.305001; - change field about { - return p1.value+p2.value+p3.value as Double; - } - - - - - Podlahová plocha prízemia - 105002 - m2 - 0 - inrange 0,1000 - - - - field: f.this, - location: f.301002, - coeff: f.205003; - change coeff about { - if (location.value=="L5") - return 1400*field.value as Double; - if (location.value=="L4") - return 900*field.value as Double; - if (location.value=="L1") - return 550*field.value as Double; - if (location.value=="L2") - return 650*field.value as Double; - if (location.value=="L3") - return 800*field.value as Double; - } - - - - - p1: f.105001, - p2: f.105002, - p3: f.105003, - field: f.305001; - change field about { - return p1.value+p2.value+p3.value as Double; - } - - - - - Podlahová plocha všetkých obytných poschodí - 105003 - m2 - Okrem prízemia - 0 - inrange 0,1000 - - - - field: f.this, - location: f.301002, - coeff: f.205004; - change coeff about { - if (location.value=="L5") - return 1200*field.value as Double; - if (location.value=="L4") - return 800*field.value as Double; - if (location.value=="L1") - return 500*field.value as Double; - if (location.value=="L2") - return 550*field.value as Double; - if (location.value=="L3") - return 700*field.value as Double; - } - - - - - p1: f.105001, - p2: f.105002, - p3: f.105003, - field: f.305001; - change field about { - return p1.value+p2.value+p3.value as Double; - } - - - - - Podlahová plocha garáže - 105004 - m2 - 0 - inrange 0,1000 - - - - field: f.this, - location: f.301002, - coeff: f.105007; - change coeff about { - if (location.value=="L5") - return 850*field.value as Double; - if (location.value=="L4") - return 700*field.value as Double; - if (location.value=="L1") - return 400*field.value as Double; - if (location.value=="L2") - return 500*field.value as Double; - if (location.value=="L3") - return 650*field.value as Double; - } - - - - - - - - - - - - - - - - - Celková podlahová plocha - 305001 - m2 - 0 - positive - - - sum: f.this, - check: f.102001, - location: f.301002, - p1: f.205002, - p2: f.205003, - p3: f.205004, - field: f.105006; - change field about { - if (check.value != "byt") - return p1.value+p2.value+p3.value as Double; - if (location.value=="L5") - return 1900*sum.value as Double; - if (location.value=="L4") - return 1300*sum.value as Double; - if (location.value=="L3") - return 950*sum.value as Double; - if (location.value=="L2") - return 700*sum.value as Double; - if (location.value=="L1") - return 650*sum.value as Double; - } - - - - - field: f.this, - location: f.301002, - coeff: f.205001; - change coeff about { - if (location.value=="L5") - return 1900*field.value as Double; - if (location.value=="L4") - return 1300*field.value as Double; - if (location.value=="L1") - return 650*field.value as Double; - if (location.value=="L2") - return 700*field.value as Double; - if (location.value=="L3") - return 950*field.value as Double; - } - - - - field: f.305001, - trans: t.363, - other: f.106003; - make other,visible on trans when { field.value > 0 } - - - field: f.305001, - trans: t.363, - other: f.106003; - make other,editable on trans when { field.value == null } - - - field: f.305001, - trans: t.363, - other: f.106003; - make other,editable on trans when { field.value == 0 as Double } - - - - field: f.this, - check: f.410001, - other: f.106003; - change other about { - if (check.value == "Nehnutelnost a domacnost" ) - return field.value as Double; - return other.value as Double; - } - - - - - f1: f.305001, - f2: f.106003, - other: f.308005; - change other about { - return Boolean.logicalAnd(f1.value != 0.0, f2.value != 0.0); - } - - - - - - - Garáž - 105035 - - - field: f.this, - other: f.105007, - trans: t.414; - make other,visible on trans when { field.value } - - - - - field: f.this, - other: f.305003, - trans: t.414; - make other,visible on trans when { field.value } - - - - - field: f.this, - other: f.105008, - trans: t.414; - make other,visible on trans when { field.value } - - - - - field: f.this, - other: f.305019, - trans: t.414; - make other,visible on trans when { field.value } - - - - - field: f.this, - other: f.105007, - trans: t.414; - make other,hidden on trans when { field.value == false } - - - - - field: f.this, - other: f.305003, - trans: t.414; - make other,hidden on trans when { field.value == false } - - - - - field: f.this, - other: f.105008, - trans: t.414; - make other,hidden on trans when { field.value == false } - - - - - field: f.this, - other: f.305019, - trans: t.414; - make other,hidden on trans when { field.value == false } - - - - - - field: f.this, - other: f.105007; - change other about { null; } - - - - - field: f.this, - other: f.305003; - change other about { null; } - - - - - field: f.this, - other: f.105008; - change other about { null; } - - - - - field: f.this, - other: f.305019; - change other about { null; } - - - - - field: f.this, - other: f.105004; - change other about { null; } - - - - - - Garáž - 105007 - Odporúčaná poistná suma - positive - - - field: f.this, - sum: f.305019; - change sum about { - return field.value as Double; - } - - - - - Garáž - 305019 - Poistná suma - inrange 1,80000 - - - field: f.305019, - check: f.105035, - exces: f.208001, - coeff: f.208003, - other: f.305003; - change other about { - return ((field.value*coeff.value*exces.value)/1000.0) as Double; - } - - - - - Garáž - 305003 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - Rovnaké miesto poistenia garáže? - 105008 - true - - - field: f.this, - coeff: f.208003; - change coeff about { - if (field.value) - return 1.0 as Double; - return 1.1 as Double; - } - - - - - field: f.305019, - check: f.105035, - exces: f.208001, - coeff: f.208003, - other: f.305003; - change other about { - return ((field.value*coeff.value*exces.value)/1000.0) as Double; - } - - - - - Hospodárska budova - 105009 - - - field: f.this, - coeff: f.205007; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - - field: f.this, - other: f.105010, - trans: t.413; - make other,editable on trans when { field.value } - - - - - field: f.this, - other: f.105010, - trans: t.413; - make other,required on trans when { field.value } - - - - - field: f.this, - other: f.305004, - trans: t.413; - make other,visible on trans when { field.value } - - - - - - field: f.this, - other: f.105010, - trans: t.413; - make other,hidden on trans when { !field.value } - - - - - field: f.this, - other: f.305004, - trans: t.413; - make other,hidden on trans when { !field.value } - - - - - - field: f.this, - other: f.105010; - change other about { null; } - - - - - field: f.this, - other: f.305004; - change other about { null; } - - - - - Hospodárska budova - 105010 - Poistná suma - positive - - - field: f.this, - coeff: f.205007, - excess: f.208001, - sum: f.305004; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Hospodárska budova - 305004 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Altánok - 105011 - - - field: f.this, - coeff: f.205008; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - - field: f.this, - other: f.105012, - trans: t.413; - make other,editable on trans when { field.value } - - - - - field: f.this, - other: f.305005, - trans: t.413; - make other,visible on trans when { field.value } - - - - - - field: f.this, - other: f.105012, - trans: t.413; - make other,hidden on trans when { return !field.value } - - - - - field: f.this, - other: f.305005, - trans: t.413; - make other,hidden on trans when { return !field.value } - - - - - - field: f.this, - other: f.105012; - change other about { null; } - - - - - field: f.this, - other: f.305005; - change other about { null; } - - - - - Altánok - 105012 - Poistná suma - positive - - - field: f.this, - coeff: f.205008, - excess: f.208001, - sum: f.305005; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Altánok - 305005 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Prístrešok - 105013 - - - field: f.this, - coeff: f.205009; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - - Prístrešok - 105014 - Poistná suma - positive - - - field: f.this, - coeff: f.205009, - excess: f.208001, - sum: f.305006; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Prístrešok - 305006 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Chodník, parkovacia plocha - 105015 - - - field: f.this, - coeff: f.205010; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Chodník, parkovacia plocha - 105016 - Poistná suma - positive - - - field: f.this, - coeff: f.205010, - excess: f.208001, - sum: f.305007; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Chodník, parkovacia plocha - 305007 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Sauna - 105017 - - - field: f.this, - coeff: f.205011; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Sauna - 105018 - Poistná suma - positive - - - field: f.this, - coeff: f.205011, - excess: f.208001, - sum: f.305008; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Sauna - 305008 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Elektrická brána - 105019 - - - field: f.this, - coeff: f.205012; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Elektrická brána, oplotenie - 105020 - Poistná suma - positive - - - field: f.this, - coeff: f.205012, - excess: f.208001, - sum: f.305009; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Elektrická brána, oplotenie - 305009 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Tenisový kurt - 105021 - - - field: f.this, - coeff: f.205013; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Tenisový kurt - 105022 - Poistná suma - positive - - - field: f.this, - coeff: f.205013, - excess: f.208001, - sum: f.305010; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Tenisový kurt - 305010 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Vonkajší bazén - 105023 - - - field: f.this, - coeff: f.205014; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Vonkajší bazén - 105024 - Poistná suma - positive - - - field: f.this, - coeff: f.205014, - excess: f.208001, - sum: f.305011; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Vonkajší bazén - 305011 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Studňa - 105025 - - - field: f.this, - coeff: f.205015; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Studňa - 105026 - Poistná suma - positive - - - field: f.this, - coeff: f.205015, - excess: f.208001, - sum: f.305012; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Studňa - 305012 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Žumpa, septik - 105027 - - - field: f.this, - coeff: f.205016; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Žumpa, septik - 105028 - Poistná suma - positive - - - field: f.this, - coeff: f.205016, - excess: f.208001, - sum: f.305013; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Žumpa, septik - 305013 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Iné - 105029 - - - field: f.this, - coeff: f.205017; - change coeff about { - if (field.value) - return 1.0 as Double; - return 0 as Double; - } - - - - - Iné - 105030 - Poistná suma - positive - - - field: f.this, - coeff: f.205017, - excess: f.208001, - sum: f.305014; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - c1: f.105010, - c2: f.105012, - c3: f.105014, - c4: f.105016, - c5: f.105018, - c6: f.105020, - c7: f.105022, - c8: f.105024, - c9: f.105026, - c10: f.105028, - c11: f.105030, - sum: f.305017; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - Iné - 305014 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - c1: f.305004, - c2: f.305005, - c3: f.305006, - c4: f.305007, - c5: f.305008, - c6: f.305009, - c7: f.305010, - c8: f.305011, - c9: f.305012, - c10: f.305013, - c11: f.305014, - sum: f.305018; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value; - } - - - - - - Celková poistná suma - inrange 1,50000 - 305017 - - - Celkové poistné - 305018 - - - - Stavebné materialy - 105031 - - - Stavebné materiály - 105032 - Poistná suma - inrange 1,5000 - - - field: f.this, - coeff: f.205018, - excess: f.208001, - sum: f.305015; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - Stavebné materiály - 305015 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - Stavebné a záhradné mechanizmy - 105033 - - - Stavebné a záhradné mechanizmy - 105034 - Poistná suma - inrange 1,7000 - - - field: f.this, - coeff: f.205019, - excess: f.208001, - sum: f.305016; - change sum about { - return ((field.value*coeff.value*excess.value)/1000.0) as Double; - } - - - - - Stavebné a záhradné mechanizmy - 305016 - Poistné - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - - Poistenie domácnosti - 106001 - 0.00 € - 50.00 € - 150.00 € - 50.00 € - Spoluúčasť - - - field: f.this, - coeff: f.208002; - change coeff about { - if (field.value=="0.00 €") - return 1.1 as Double; - if (field.value=="50.00 €") - return 1.0 as Double; - if (field.value=="150.00 €") - return 0.9 as Double; - } - - - - - field: f.106022, - field2: f.106023, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field2.value*field.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - check: f.this, - trans: t.364, - other: f.106002; - make other,visible on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,editable on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.106022; - make other,required on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.106023; - make other,editable on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.106023; - make other,required on trans when { check.value != null } - - - - - check: f.this, - trans: t.364, - other: f.306001; - make other,visible on trans when { check.value != null } - - - - - - Odporúčaná poistná suma - 106002 - Poistná suma - positive - - - field: f.106002, - check: f.103002, - other: f.106022; - change other about { - if (check.value=="trvalá") - return field.value as Double; - return 1.0 as Double; - } - - - - - field: f.106002, - check: f.103002, - other: f.106023; - change other about { - if(check.value=="dočasná") - return field.value as Double; - return 1.0 as Double; - } - - - - - - Poistná suma - 106022 - Poistná suma - inrange 1,300000 - - - field: f.106022, - field2: f.106023, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field.value*field2.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - - Poistná suma - 106023 - Poistná suma - inrange 1,50000 - - - field: f.106023, - field2: f.106022, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field.value*field2.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - Poistenie domácnosti - 306001 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - - Celková podlahová plocha - 106003 - 0 - positive - - - - - - - - - - - - - - - - - - - - - - field: f.this, - coeff: f.106002; - change coeff about { - if (field.value > 100) - return 25000 + (field.value - 100) * 100 as Double; - return 250*field.value as Double; - } - - - - - f1: f.305001, - f2: f.106003, - other: f.308005; - change other about { - return Boolean.logicalAnd(f1.value != 0.0, f2.value != 0.0); - } - - - - - Cennosti - 106004 - - - Cennosti - 106005 - inrange 0,10000 - - Poistná suma - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Cennosti - 306002 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Umelecké diela - 106006 - - - Umelecké diela - 106007 - Poistná suma - inrange 0,5000 - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Umelecké diela - 306003 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Elektronické a optické zariadenia - 106008 - - - Elektronické a optické zariadenia - 106009 - Poistná suma - inrange 0,10000 - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Elektronické a optické zariadenia - 306004 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Špecialne sklá a presklenie - 106010 - - - Špeciálne sklá a presklenie - 106011 - inrange 0,2000 - Poistná suma - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Špeciálne sklá a presklenie - 306005 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Záhradné vybavenie a nábytok - 106012 - - - Záhradé vybavenie a nábytok - 106013 - inrange 0,2000 - Poistná suma - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Záhradé vybavenie a nábytok - 306006 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Elektromotory v domácich spotrebičoch - 106014 - - - Elektromotory v domácich spotrebičoch - 106015 - inrange 0,300 - Poistná suma - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Elektromotory v domácich spotrebičoch - 306007 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Stavebné súčasti domácnosti - 106016 - - - Stavebné súčasti domácností - 106017 - inrange 0,30000 - Poistná suma - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Stavebné súčasti domácností - 306008 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Športové náradie - 106018 - - - Športové náradie - 106019 - inrange 0,5000 - Poistná suma - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - športové náradie - 306009 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Iné - 106020 - - - Iné - 106021 - Poistná suma - inrange 0,2000 - - - c1: f.106005, - c2: f.106007, - c3: f.106009, - c4: f.106011, - c5: f.106013, - c6: f.106015, - c7: f.106017, - c8: f.106019, - c9: f.106021, - sum: f.106024; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Iné - 306010 - Poistné - - - c1: f.306001, - c2: f.306002, - c3: f.306003, - c4: f.306004, - c5: f.306005, - c6: f.306006, - c7: f.306007, - c8: f.306008, - c9: f.306009, - c10: f.306010, - sum: f.308002; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value; - } - - - - - c1: f.306002, - c2: f.306003, - c3: f.306004, - c4: f.306005, - c5: f.306006, - c6: f.306007, - c7: f.306008, - c8: f.306009, - c9: f.306010, - sum: f.106025; - change sum about { - return c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value; - } - - - - - Celková poistná suma - 106024 - positive - - - Celkové poistné - 106025 - positive - - - - - Poistenie zodpovednosti z vlastníctva nehnuteľnosti do výšky - 107001 - Poistná suma - 120,000.00 € - 60,000.00 € - 30,000.00 € - 15,000.00 € - 0.00 € - - - field: f.this, - coeff: f.204001; - change coeff about { - if (field.value == "0.00 €") - return 0.0 as Double; - return 0.2 as Double; - } - - - - - field: f.this, - coeff: f.204001, - excess: f.208001, - sum: f.308008; - change sum about { - def n = field.value.getDefaultValue().replaceAll("[,€ ]","") as Double; - return ((n*coeff.value*excess.value)/1000.0) as Double; - } - - - - - check: f.this, - trans: t.364, - other: f.308008; - make other,hidden on trans when { check.value == "0.00 €" } - - - - - check: f.this, - trans: t.364, - other: f.308008; - make other,visible on trans when { check.value != "0.00 €" } - - - - - check: f.107003, - check2: f.107001, - trans: t.364, - other: f.308003; - make other,hidden on trans when { Boolean.logicalAnd(check.value == "0.00 €", check2.value == "0.00 €") } - - - - - Zodpovednosť za škodu členov domácnosti - 107003 - Eur - 120,000.00 € - 60,000.00 € - 30,000.00 € - 15,000.00 € - 0.00 € - - - field: f.this, - coeff: f.204002; - change coeff about { - if (field.value == "0.00 €") - return 0.0 as Double; - return 0.2 as Double; - } - - - - - field: f.107003, - coeff: f.204003, - excess: f.208002, - sum: f.308009; - change sum about { - def n = field.value.getDefaultValue().replaceAll("[,€ ]","") as Double; - return ((n*coeff.value*excess.value)/1000.0) as Double; - } - - - - - check: f.this, - trans: t.363, - other: f.104003; - make other,editable on trans when { check.value != "0.00 €" } - - - - - check: f.this, - trans: t.363, - other: f.104003; - make other,required on trans when { check.value != "0.00 €" } - - - - - check: f.this, - trans: t.363, - other: f.104003; - make other,hidden on trans when { check.value == "0.00 €" } - - - - - check: f.this, - other: f.104003; - change other about { - if (check.value == "0.00 €") - return null; - return other.value; - } - - - - - check: f.this, - trans: t.364, - other: f.308009; - make other,visible on trans when { check.value != "0.00 €" } - - - - - check: f.this, - trans: t.364, - other: f.308003; - make other,visible on trans when { check.value != "0.00 €" } - - - - - check: f.this, - trans: t.364, - other: f.308009; - make other,hidden on trans when { check.value == "0.00 €" } - - - - - check: f.107003, - check2: f.107001, - trans: t.364, - other: f.308003; - make other,hidden on trans when { Boolean.logicalAnd(check.value == "0.00 €", check2.value == "0.00 €") } - - - - - - field: f.this, - other: f.308009; - change other about { null; } - - - - - check: f.this, - trans: t.364, - other: f.108005; - make other,visible on trans when { check.value != null } - - - - - - Celkové poistenie nehnuteľnosti - 308001 - Poistné - - - s1: f.308001, - s2: f.308002, - s3: f.308003, - sum: f.308004; - change sum about { - return s1.value+s2.value+s3.value as Double; - } - - - - - Poistenie nehnuteľnosti - 305002 - Poistné - 0 - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - Odporúčaná poistná suma - 105006 - Poistná suma - positive - - - field: f.105006, - other: f.105036; - change other about { - return field.value as Double; - } - - - - - Poistná suma - 105036 - Poistná suma - inrange 1,700000 - - - field: f.105036, - excess: f.208001, - hhc: f.202009, - sadzba: f.201019, - bic: f.201017, - sum: f.305002; - change sum about { - return ((field.value*excess.value*hhc.value*bic.value*sadzba.value)/1000.0) as Double; - } - - - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - Celkové poistenie domácnosti - 308002 - Poistné - - - s1: f.308001, - s2: f.308002, - s3: f.308003, - sum: f.308004; - change sum about { - return s1.value+s2.value+s3.value as Double; - } - - - - - Poistenie zodpovednosti z vlastníctva nehnuteľnosti - 308008 - Poistné - - - c1: f.308008, - c2: f.308009, - sum: f.308003; - change sum about { - return c1.value+c2.value as Double; - } - - - - - Zodpovednosť za škodu členov domácnosti - 308009 - Poistné - - - c1: f.308008, - c2: f.308009, - sum: f.308003; - change sum about { - return c1.value+c2.value as Double; - } - - - - - Celkové poistenie zodpovednosti za škodu - 308003 - Poistné - - - s1: f.308001, - s2: f.308002, - s3: f.308003, - sum: f.308004; - change sum about { - return s1.value+s2.value+s3.value as Double; - } - - - - - ROČNÉ POISTNÉ CELKOM - 308004 - - - c1: f.308004, - c2: f.208004, - c3: f.208008, - c4: f.208005, - c5: f.208006, - c6: f.208007, - c7: f.203004, - sum: f.308006; - change sum about { - return (Math.round(100.0*c1.value*c2.value*c3.value*c4.value*c5.value*c6.value*c7.value/4.0)/100.0)*4.0 as - Double; - } - - - - - PERIODICITA PLATBY POISTNÉHO - 108001 - ročná - polročná - štvrťročná - ročná - - - field: f.this, - coeff: f.208004; - change coeff about { - if (field.value == "ročná") - return 0.95 as Double; - if (field.value == "polročná") - return 0.99 as Double; - if (field.value == "štvrťročná") - return 1.0 as Double; - } - - - - - check: f.108001, - field: f.308006, - sum: f.308010; - change sum about { - if (check.value=="ročná") - return field.value as Double; - if (check.value=="polročná") - return field.value/2 as Double; - if (check.value=="štvrťročná") - return field.value/4 as Double; - } - - - - - c1: f.308004, - c2: f.208004, - c3: f.208008, - c4: f.208005, - c5: f.208006, - c6: f.208007, - c7: f.203004, - sum: f.308006; - change sum about { - return (Math.round(100.0*c1.value*c2.value*c3.value*c4.value*c5.value*c6.value*c7.value/4.0)/100.0)*4.0 as - Double; - } - - - - - KOMPLETNÉ POISTENIE - 308005 - - - field: f.this, - coeff: f.208008; - change coeff about { - if (field.value) - return 0.95 as Double; - return 1.0 as Double; - } - - - - - c1: f.308004, - c2: f.208004, - c3: f.208008, - c4: f.208005, - c5: f.208006, - c6: f.208007, - c7: f.203004, - sum: f.308006; - change sum about { - return (Math.round(100.0*c1.value*c2.value*c3.value*c4.value*c5.value*c6.value*c7.value/4.0)/100.0)*4.0 as - Double; - } - - - - - ZĽAVA ZA INÉ POISTENIE V PREMIUM - 108002 - - - field: f.this, - coeff: f.208005; - change coeff about { - if (field.value) - return 0.95 as Double; - return 1.0 as Double; - } - - - - - c1: f.308004, - c2: f.208004, - c3: f.208008, - c4: f.208005, - c5: f.208006, - c6: f.208007, - c7: f.203004, - sum: f.308006; - change sum about { - return (Math.round(100.0*c1.value*c2.value*c3.value*c4.value*c5.value*c6.value*c7.value/4.0)/100.0)*4.0 as - Double; - } - - - - - - ZABEZPEČENIE DOMÁCNOSTI ALARMOM - 108005 - - - - OBCHODNÁ ZĽAVA - 108003 - 0% - 5% - 10% - 15% - 20% - 25% - - - field: f.this, - coeff: f.208006; - change coeff about { - if (field.value=="0%") - return 1.0 as Double; - if (field.value=="5%") - return 0.95 as Double; - if (field.value=="10%") - return 0.9 as Double; - if (field.value=="15%") - return 0.85 as Double; - if (field.value=="20%") - return 0.8 as Double; - if (field.value=="25%") - return 0.75 as Double; - } - - - - - c1: f.308004, - c2: f.208004, - c3: f.208008, - c4: f.208005, - c5: f.208006, - c6: f.208007, - c7: f.203004, - sum: f.308006; - change sum about { - return (Math.round(100.0*c1.value*c2.value*c3.value*c4.value*c5.value*c6.value*c7.value/4.0)/100.0)*4.0 as - Double; - } - - - - - AKCIOVÁ ZĽAVA - 108004 - - - field: f.this, - coeff: f.208007; - change coeff about { - if (field.value) - return 0.9 as Double; - return 1.0 as Double; - } - - - - - c1: f.308004, - c2: f.208004, - c3: f.208008, - c4: f.208005, - c5: f.208006, - c6: f.208007, - c7: f.203004, - sum: f.308006; - change sum about { - return (Math.round(100.0*c1.value*c2.value*c3.value*c4.value*c5.value*c6.value*c7.value/4.0)/100.0)*4.0 as - Double; - } - - - - - BEŽNÉ POISTNÉ - 308006 - - - check: f.108001, - field: f.308006, - sum: f.308010; - change sum about { - if (check.value=="ročná") - return field.value as Double; - if (check.value=="polročná") - return field.value/2 as Double; - if (check.value=="štvrťročná") - return field.value/4 as Double; - } - - - - - Výška splátky poistného - 308010 - inrange 20,inf - - - - Koeficient - Lokalita nehnutelnosť - 201001 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Lokalita sadzba domácnosť - 201018 - 1 - - - Koeficient - Lokalita sadzba nehnutelnosť - 201019 - 1 - - - Koeficient - Nachádza sa mimo obce (extravilán)? - 201002 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Bolo miesto poistenia postihnuté povodňou za posledných 10 rokov? - 201003 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Nachádza nehnuteľnosť sa vo vzdialenosti kratšej ako 300 m od vodného toku? - 201004 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Koľko rokov žijete v poisťovanej nehnuteľnosti? - 201005 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Aký je vzťah poisteného k poisťovanej nehnuteľnosti? - 201006 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Koľko dospelých žije v domácnosti? - 201007 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Koľko detí žije v domácnosti? - 201008 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Žije v poisťovanej domácnosti pes alebo mačka? - 201012 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - Koeficient - Je nehnuteľnosť využívaná aj na podnikanie? - 201014 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - - Koeficient - Počet poistných udalostí za posledné 3 roky? - 201016 - 1 - - - c2: f.201002, - c3: f.201003, - c4: f.201004, - c5: f.201005, - c6: f.201006, - c7: f.201007, - c8: f.201008, - c12: f.201012, - c14: f.201014, - c16: f.201016, - sum: f.201017; - change sum about { - return c2.value*c3.value*c4.value*c5.value*c6.value*c7.value*c8.value*c12.value*c14.value*c16.value; - } - - - - - ZÁKLADNÉ INFORMÁCIE koeficient - 201017 - 1 - - - field: f.105036, - excess: f.208001, - hhc: f.202009, - sadzba: f.201019, - bic: f.201017, - sum: f.305002; - change sum about { - return ((field.value*excess.value*hhc.value*bic.value*sadzba.value)/1000.0) as Double; - } - - - - - field: f.106022, - field2: f.106023, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field.value*field2.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - - Koeficient - Poistenie nehnuteľnosti - spoluúčasť - 208001 - 1 - - - Koeficient - Predmet poistenia - 202001 - 1 - - - c1: f.202001, - c2: f.202002, - c3: f.202003, - c4: f.202004, - c6: f.202006, - c7: f.202007, - sum: f.202009; - change sum about { - return c1.value*c2.value*c3.value*c4.value*c6.value*c7.value; - } - - - - - Koeficient - Konštrukcia múrov - 202002 - 1 - - - c1: f.202001, - c2: f.202002, - c3: f.202003, - c4: f.202004, - c6: f.202006, - c7: f.202007, - sum: f.202009; - change sum about { - return c1.value*c2.value*c3.value*c4.value*c6.value*c7.value; - } - - - - - Koeficient - Konštrukcia strechy - 202003 - 1 - - - c1: f.202001, - c2: f.202002, - c3: f.202003, - c4: f.202004, - c6: f.202006, - c7: f.202007, - sum: f.202009; - change sum about { - return c1.value*c2.value*c3.value*c4.value*c6.value*c7.value; - } - - - - - Koeficient - Koľko rokov má nehnuteľnosť? - 202004 - 1.02 - - - c1: f.202001, - c2: f.202002, - c3: f.202003, - c4: f.202004, - c6: f.202006, - c7: f.202007, - sum: f.202009; - change sum about { - return c1.value*c2.value*c3.value*c4.value*c6.value*c7.value; - } - - - - - Koeficient - Koľko izieb má nehnuteľnosť? - 202006 - 1 - - - c1: f.202001, - c2: f.202002, - c3: f.202003, - c4: f.202004, - c6: f.202006, - c7: f.202007, - sum: f.202009; - change sum about { - return c1.value*c2.value*c3.value*c4.value*c6.value*c7.value; - } - - - - - Koeficient - Koľko kúpeľní má nehnuteľnosť? - 202007 - 1 - - - c1: f.202001, - c2: f.202002, - c3: f.202003, - c4: f.202004, - c6: f.202006, - c7: f.202007, - sum: f.202009; - change sum about { - return c1.value*c2.value*c3.value*c4.value*c6.value*c7.value; - } - - - - - NEHNUTEĽNOSŤ koeficient - 202009 - 0.945 - - - field: f.105036, - excess: f.208001, - hhc: f.202009, - sadzba: f.201019, - bic: f.201017, - sum: f.305002; - change sum about { - return ((field.value*excess.value*hhc.value*bic.value*sadzba.value)/1000.0) as Double; - } - - - - - - Koeficient - Poistenie domácnosti - spoluúčasť - 208002 - 1 - - - field: f.106022, - field2: f.106023, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field.value*field2.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - Koeficient - Umiestnenie domácnosti - 203001 - 1.0 - - - c1: f.203001, - c2: f.203002, - c5: f.203005, - sum: f.203006; - change sum about { - return c1.value*c2.value*c5.value; - } - - - - - Koeficient - Obývanosť domácnosti - 203002 - 1.0 - - - c1: f.203001, - c2: f.203002, - c5: f.203005, - sum: f.203006; - change sum about { - return c1.value*c2.value*c5.value; - } - - - - - Koeficient - Je domácnosť zabezpečená funkčným alarmom? - 203004 - 1.0 - - - - - - - - - - - - - - - Koeficient - Má domácnosť na oknách vo výške do 3 metrov od okolitého terénu mreže / vonkajšie žalúzie - alebo rolety? - - 203005 - 1.0 - - - c1: f.203001, - c2: f.203002, - c5: f.203005, - sum: f.203006; - change sum about { - return c1.value*c2.value*c5.value; - } - - - - - DOMÁCNOSŤ koeficient - 203006 - 0.95 - - - field: f.106022, - field2: f.106023, - excess: f.208002, - loc: f.201001, - ppc: f.203006, - bic: f.201017, - sum: f.306001; - change sum about { - return ((field.value*field2.value*excess.value*ppc.value*bic.value*loc.value)/1000.0) as Double; - } - - - - - - Koeficient - Poistenie zodpovednosti z vlastníctva nehnuteľnosti - 204001 - - - Koeficient - Zodpovednosť za škodu členov domácnosti - 204002 - 0 - - - Koeficient - Územná platnosť poistenia - 204003 - 1 - - - Koeficient - Zodpovednosť celkovo - 204004 - 0 - - - - Koeficient - PERIODICITA PLATBY POISTNÉHO - 208004 - 0.95 - - - Koeficient - ZĽAVA ZA INÉ POISTENIE V PREMIUM - 208005 - 1 - - - Koeficient - OBCHODNÁ ZĽAVA - 208006 - 1 - - - Koeficient - AKCIOVÁ ZĽAVA - 208007 - 1 - - - Koeficient - KOMPLETNÉ POISTENIE - 208008 - 1 - - - - Koeficient - Lokalita - byt - 205001 - 0 - - - field: f.105036, - excess: f.208001, - hhc: f.202009, - sadzba: f.201019, - bic: f.201017, - sum: f.305002; - change sum about { - return ((field.value*excess.value*hhc.value*bic.value*sadzba.value)/1000.0) as Double; - } - - - - - c1: f.305002, - c2: f.305003, - c3: f.305004, - c4: f.305005, - c5: f.305006, - c6: f.305007, - c7: f.305008, - c8: f.305009, - c9: f.305010, - c10: f.305011, - c11: f.305012, - c12: f.305013, - c13: f.305014, - c14: f.305015, - c15: f.305016, - sum: f.308001; - change sum about { - return - c1.value+c2.value+c3.value+c4.value+c5.value+c6.value+c7.value+c8.value+c9.value+c10.value+c11.value+c12.value+c13.value+c14.value+c15.value; - } - - - - - Koeficient - Lokalita - pivnica - 205002 - 0 - - - Koeficient - Lokalita - prízemie - 205003 - 0 - - - Koeficient - Lokalita - obytné poschodie - 205004 - 0 - - - Koeficient - Lokalita - garáž - 205005 - - - Koeficient - Garáž - 205006 - - - Koeficient - Garáž umiestnenie - 208003 - 1 - - - Koeficient - Hospodárska budova - 205007 - - - Koeficient - Altánok - 205008 - - - Koeficient - Prístrešok - 205009 - - - Koeficient - Chodník, parkovacia plocha - 205010 - - - - Koeficient - Sauna - 205011 - - - Koeficient - Elektrická brána, oplotenie - 205012 - - - Koeficient - Tenisový kurt - 205013 - - - Koeficient - Vonkajší bazén - 205014 - - - Koeficient - Studňa - 205015 - - - Koeficient - Žumpa, septik - 205016 - - - Koeficient - Iné - 205017 - - - Koeficient - Stavebné materiály - 205018 - - - Koeficient - Stavebné a záhradné mechanizmy - 205019 - - - - Koeficient - Cennosti - 206001 - - - Koeficient - Umelecké diela - 206002 - - - Koeficient - Elektronické a optické zariadneia - 206003 - - - Koeficient - Špecialne sklá a presklenie - 206004 - - - Koeficient - Záhradné vybavenie a nábytok - 206005 - - - Koeficient - Elektromotory v domácich spotrebičoch - 206006 - - - Koeficient - Stavebné súčasti domácností - 206007 - - - Koeficient - Športové náradie - 206008 - - - Koeficient - Iné - 206009 - - - Koeficient - Domácnosť - lokalita - 206010 - - - - Koeficient - Poistenie zodpovednosti z vlastníctva nehnuteľnosti - 207001 - - - Koeficient - Zodpovednosť za škodu členov domácnosti - 207002 - - - - - - - Číslo zmluvy - 309001 - 0000000000 - - - field: f.this; - generate "Insurance.offerId",once into field - - - - - field: f.this, - other: f.308007; - change other about { - return field.value; - } - - - - - Začiatok poistenia - 109001 - - - Poistenie na dobu určitú - 109002 - - - field: f.this, - other: f.109003, - trans: t.1661; - make other,editable on trans when { field.value } - - - - - field: f.this, - other: f.109003, - trans: t.332; - make other,editable on trans when { field.value } - - - - - field: f.this, - other: f.109003, - trans: t.1618; - make other,editable on trans when { field.value } - - - - - field: f.this, - other: f.109003, - trans: t.1661; - make other,hidden on trans when { !field.value } - - - - - field: f.this, - other: f.109003, - trans: t.332; - make other,hidden on trans when { !field.value } - - - - - field: f.this, - other: f.109003, - trans: t.1618; - make other,hidden on trans when { !field.value } - - - - - Koniec poistenia - 109003 - - - V prospech - 109004 - Údaje o vinkulácii - - - Číslo úverovej zmluvy - 109005 - Údaje o vinkulácii - - - 109060 - Zriaďuje sa indexácia poistnej sumy? - - - Spôsob platenia - 109006 - prevodom - vkladom alebo poštovou poukážkou - - - field: f.this, - other: f.109065, - trans: t.1661; - make other,editable on trans when { field.value == "vkladom alebo poštovou poukážkou" } - - - - - field: f.this, - other: f.109065, - trans: t.332; - make other,editable on trans when { field.value == "vkladom alebo poštovou poukážkou" } - - - - - field: f.this, - other: f.109065, - trans: t.1618; - make other,editable on trans when { field.value == "vkladom alebo poštovou poukážkou" } - - - - - - field: f.this, - other: f.109065, - trans: t.1661; - make other,required on trans when { field.value == "vkladom alebo poštovou poukážkou" } - - - - - field: f.this, - other: f.109065, - trans: t.332; - make other,required on trans when { field.value == "vkladom alebo poštovou poukážkou" } - - - - - field: f.this, - other: f.109065, - trans: t.1618; - make other,required on trans when { field.value == "vkladom alebo poštovou poukážkou" } - - - - - - field: f.this, - other: f.109065, - trans: t.1661; - make other,hidden on trans when { field.value == "prevodom" } - - - - - field: f.this, - other: f.109065, - trans: t.332; - make other,hidden on trans when { field.value == "prevodom" } - - - - - field: f.this, - other: f.109065, - trans: t.1618; - make other,hidden on trans when { field.value == "prevodom" } - - - - - - field: f.this, - other: f.109065; - change other about { return null; } - - - - - 109065 - Pôvod finančných prostriedkov - - - 109066 - Osobitné vyjadrenia týkajúce sa poisteného alebo poistníka - area - - - 109067 - Poistník udeľuje poisťovateľovi súhlas so spracovaním osobných údajov na marketingové účely - - - - - Typ subjektu - 109007 - Poistník - fyzická osoba - právnická osoba - fyzická osoba podnikateľ (SZČO) - fyzická osoba - - - field: f.109020, - f_1: f.109007, - f_2: f.109021; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - - check: f.109007, - field: f.109058, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109058, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109058, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109007, - field: f.109058, - trans: t.588; - make field,required on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109007, - field: f.109058, - trans: t.588; - make field,editable on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109007, - field: f.109058; - change field about { - if (check.value == "fyzická osoba") - return null; - return field.value; - } - - - - - - check: f.109007, - field: f.109012, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109012, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109012, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109007, - field: f.109012, - trans: t.588; - make field,required on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109007, - field: f.109012, - trans: t.588; - make field,editable on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109007, - field: f.109012; - change field about { - if (check.value == "fyzická osoba") - return null; - return field.value; - } - - - - - - check: f.109007, - field: f.109061, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109061, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109061, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109007, - field: f.109061, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109007, - field: f.109061; - change field about { - if (check.value == "právnická osoba") - return field.value; - return null; - } - - - - - - check: f.109007, - field: f.109062, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109062, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109007, - field: f.109062, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109007, - field: f.109062, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109007, - field: f.109062; - change field about { - if (check.value == "právnická osoba") - return field.value; - return null; - } - - - - - Titul pred menom - 109008 - Poistník - - - field: f.109020, - f_1: f.109008, - f_2: f.109022; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Titul za menom - 109009 - Poistník - - - field: f.109020, - f_1: f.109009, - f_2: f.109023; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Meno - 109010 - Poistník - - - field: f.109020, - f_1: f.109010, - f_2: f.109024; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Priezvisko - 109011 - Poistník - - - field: f.109020, - f_1: f.109011, - f_2: f.109025; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Obchodné meno - 109012 - Poistník - - - field: f.109020, - f_1: f.109012, - f_2: f.109026; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Štátna príslušnosť - 109013 - Poistník - SR - CZ - HU - PL - AT - Iná - - - field: f.109020, - f_1: f.109013, - f_2: f.109027; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Dátum narodenia - 109014 - Poistník - - - field: f.109020, - f_1: f.109014, - f_2: f.109028; - change f_2 about { - if (field.value == false) - return f_1.value; - return f_2.value; - } - - - - - Rodné číslo - 109015 - Poistník - - - field: f.109020, - f_1: f.109015, - f_2: f.109029; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Typ preukazu - 109016 - Poistník - pas - OP - iné - - - check: f.this, - other: f.109015, - trans: t.588; - make other,hidden on trans when { check.value != "OP" } - - - - - check: f.this, - other: f.109015, - trans: t.588; - make other,editable on trans when { check.value == "OP" } - - - - - check: f.this, - other: f.109015, - trans: t.588; - make other,required on trans when { check.value == "OP" } - - - - - field: f.109020, - f_1: f.109016, - f_2: f.109030; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Číslo preukazu - 109017 - Poistník - - - field: f.109020, - f_1: f.109017, - f_2: f.109031; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Telefónne číslo - 109018 - Poistník - telnumber - - - field: f.109020, - f_1: f.109018, - f_2: f.109032; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Email - 109019 - email - Poistník - - - field: f.109020, - f_1: f.109019, - f_2: f.109033; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - Štát - 109060 - Poistník - - - V zastúpení - 109061 - Poistník - - - Funkcia - 109062 - Poistník - - - - Poistený je iná osoba - 109020 - false - Poistený a poistenec sú rôzne osoby - - - field: f.this, - other: f.109021, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109022, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109023, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109024, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109024, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109025, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109025, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109027, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109027, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109028, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109028, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109029, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109029, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109030, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109030, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109031, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109031, - trans: t.588; - make other,required on trans when { field.value } - - - field: f.this, - other: f.109032, - trans: t.588; - make other,editable on trans when { field.value } - - - field: f.this, - other: f.109033, - trans: t.588; - make other,editable on trans when { field.value } - - - - - field: f.109020, - f_1: f.109007, - f_2: f.109021; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109008, - f_2: f.109022; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109009, - f_2: f.109023; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109010, - f_2: f.109024; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109011, - f_2: f.109025; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109012, - f_2: f.109026; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109013, - f_2: f.109027; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109014, - f_2: f.109028; - change f_2 about { - if (field.value == false) - return f_1.value; - return f_2.value; - } - - - - - field: f.109020, - f_1: f.109015, - f_2: f.109029; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109016, - f_2: f.109030; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109017, - f_2: f.109031; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109018, - f_2: f.109032; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109019, - f_2: f.109033; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109058, - f_2: f.109059; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109061, - f_2: f.109063; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.109020, - f_1: f.109062, - f_2: f.109064; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - field: f.this, - other: f.109021, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109022, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109023, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109024, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109025, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109026, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109027, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109028, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109029, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109030, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109031, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109032, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109033, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109059, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109063, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - field: f.this, - other: f.109064, - trans: t.588; - make other,hidden on trans when { return !field.value } - - - - IČO - 109058 - Poistník - - - field: f.109020, - f_1: f.109058, - f_2: f.109059; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - 109061 - V zastúpení - Poistník - - - field: f.109020, - f_1: f.109061, - f_2: f.109063; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - 109062 - Funkcia konateľa - Poistník - - - field: f.109020, - f_1: f.109062, - f_2: f.109064; - change f_2 about { - if (field.value == false) - return f_1.value as String; - return null; - } - - - - - - Typ subjektu - 109021 - Poistený - fyzická osoba - právnická osoba - fyzická osoba podnikateľ (SZČO) - fyzická osoba - - - - check: f.109021, - field: f.109059, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109059, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109059, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109021, - field: f.109059, - trans: t.588; - make field,required on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109059, - trans: t.588; - make field,editable on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109059; - change field about { - if (check.value == "fyzická osoba") - return null; - return field.value; - } - - - - - - check: f.109021, - field: f.109026, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109026, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109026, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109021, - field: f.109026, - trans: t.588; - make field,required on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109026, - trans: t.588; - make field,editable on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109026; - change field about { - if (check.value == "fyzická osoba") - return null; - return field.value; - } - - - - - - check: f.109021, - field: f.109029, - trans: t.588; - make field,hidden on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109029, - trans: t.588; - make field,required on trans when { check.value == "fyzická osoba" } - - - - - check: f.109021, - field: f.109029, - trans: t.588; - make field,editable on trans when { check.value == "fyzická osoba" } - - - - - check: f.109021, - field: f.109029, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109029; - change field about { - if (check.value == "fyzická osoba") - return field.value; - return null; - } - - - - - - check: f.109021, - field: f.109063, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109063, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109063, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109021, - field: f.109063, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109063; - change field about { - if (check.value == "právnická osoba") - return field.value; - return null; - } - - - - - - check: f.109021, - field: f.109064, - trans: t.588; - make field,editable on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109064, - trans: t.588; - make field,required on trans when { check.value == "právnická osoba" } - - - - - check: f.109021, - field: f.109064, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba" } - - - - - check: f.109021, - field: f.109064, - trans: t.588; - make field,hidden on trans when { check.value == "fyzická osoba podnikateľ (SZČO)" } - - - - - check: f.109021, - field: f.109064; - change field about { - if (check.value == "právnická osoba") - return field.value; - return null; - } - - - - - Titul pred menom - 109022 - Poistený - - - Titul za menom - 109023 - Poistený - - - Meno - 109024 - Poistený - - - Priezvisko - 109025 - Poistený - - - Obchodné meno - 109026 - Poistený - - - Štátna príslušnosť - 109027 - Poistený - SK - CZ - HU - PL - Iná - SK - - - Dátum narodenia - 109028 - Poistený - - - Rodné číslo - 109029 - - Poistený - - - Typ preukazu - 109030 - Poistený - pas - OP - iné - - - check: f.this, - other: f.109029, - trans: t.588; - make other,hidden on trans when { check.value != "OP" } - - - - - check: f.this, - check2: f.109020, - other: f.109029, - trans: t.588; - make other,editable on trans when { Boolean.logicalAnd(check.value == "OP", check2.value as Boolean) } - - - - - check: f.this, - check2: f.109020, - other: f.109029, - trans: t.588; - make other,required on trans when { Boolean.logicalAnd(check.value == "OP", check2.value as Boolean) } - - - - - Číslo preukazu - 109031 - Poistený - - - Telefónne číslo - 109032 - Poistený - telnumber - - - Email - 109033 - email - Poistený - - - IČO - 109059 - Poistený - - - 109063 - V zastúpení - Poistený - - - 109064 - Funkcia konateľa - Poistený - - - - - Rovnaká ako miesto poistenia - 109035 - Adresa trvalého pobytu - true - - - field: f.this, - other: f.109036, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109037, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109038, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109039, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109036, - trans: t.588; - make other,required on trans when { !field.value } - - - field: f.this, - other: f.109037, - trans: t.588; - make other,required on trans when { !field.value } - - - field: f.this, - other: f.109038, - trans: t.588; - make other,required on trans when { !field.value } - - - field: f.this, - other: f.109039, - trans: t.588; - make other,required on trans when { !field.value } - - - - field: f.this, - other: f.109036, - trans: t.588; - make other,hidden on trans when { field.value } - - - field: f.this, - other: f.109037, - trans: t.588; - make other,hidden on trans when { field.value } - - - field: f.this, - other: f.109038, - trans: t.588; - make other,hidden on trans when { field.value } - - - field: f.this, - other: f.109039, - trans: t.588; - make other,hidden on trans when { field.value } - - - - - field: f.109035, - f_1: f.109045, - f_2: f.109036; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - field: f.this, - f_1: f.109046, - f_2: f.109037; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - field: f.this, - f_1: f.109047, - f_2: f.109038; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - field: f.this, - f_1: f.109048, - f_2: f.109039; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - Ulica - 109036 - Trvalý pobyt/Sídlo - - - field: f.109034, - f_1: f.109036, - f_2: f.109041; - change f_2 about { - if (field.value) - return f_1.value as String; - return f_2.value; - } - - - - - Súpisné a orientačné číslo - 109037 - Trvalý pobyt/Sídlo - - - field: f.109034, - f_1: f.109037, - f_2: f.109042; - change f_2 about { - if (field.value) - return f_1.value as String; - return f_2.value; - } - - - - - PSČ - 109038 - Trvalý pobyt/Sídlo - - - field: f.109034, - f_1: f.109038, - f_2: f.109043; - change f_2 about { - if (field.value) - return f_1.value as String; - return f_2.value; - } - - - - - Obec - 109039 - Trvalý pobyt/Sídlo - - - field: f.109034, - f_1: f.109039, - f_2: f.109044; - change f_2 about { - if (field.value) - return f_1.value as String; - return f_2.value; - } - - - - - - Rovnaká ako trvalý pobyt - 109034 - Korešpondenčná adresa - true - - - field: f.this, - other: f.109041, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109042, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109043, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109044, - trans: t.588; - make other,editable on trans when { !field.value } - - - field: f.this, - other: f.109041, - trans: t.588; - make other,required on trans when { !field.value } - - - field: f.this, - other: f.109042, - trans: t.588; - make other,required on trans when { !field.value } - - - field: f.this, - other: f.109043, - trans: t.588; - make other,required on trans when { !field.value } - - - field: f.this, - other: f.109044, - trans: t.588; - make other,required on trans when { !field.value } - - - - field: f.this, - other: f.109041, - trans: t.588; - make other,hidden on trans when { field.value } - - - field: f.this, - other: f.109042, - trans: t.588; - make other,hidden on trans when { field.value } - - - field: f.this, - other: f.109043, - trans: t.588; - make other,hidden on trans when { field.value } - - - field: f.this, - other: f.109044, - trans: t.588; - make other,hidden on trans when { field.value } - - - - - field: f.109034, - f_1: f.109036, - f_2: f.109041; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - field: f.109034, - f_1: f.109037, - f_2: f.109042; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - field: f.109034, - f_1: f.109038, - f_2: f.109043; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - field: f.109034, - f_1: f.109039, - f_2: f.109044; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - Ulica - 109041 - Korešpondenčná adresa - - - Súpisné a orientačné číslo - 109042 - Korešpondenčná adresa - - - PSČ - 109043 - Korešpondenčná adresa - - - Obec - 109044 - Korešpondenčná adresa - - - - Ulica - 109045 - Miesto poistenia - - - field: f.109035, - f_1: f.109045, - f_2: f.109036; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - Súpisné a orientačné číslo - 109046 - Miesto poistenia - - - field: f.109035, - f_1: f.109046, - f_2: f.109037; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - PSČ - 109047 - Miesto poistenia - - - field: f.109035, - f_1: f.109047, - f_2: f.109038; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - Obec - 109048 - Miesto poistenia - - - field: f.109035, - f_1: f.109048, - f_2: f.109039; - change f_2 about { - if (field.value) - return f_1.value as String; - return null; - } - - - - - - Ulica - 109054 - Garáž - - - Súpisné a orientačné číslo - 109055 - Garáž - - - PSČ - 109056 - Garáž - - - Obec - 109057 - Garáž - - - - Variabilný symbol - 308007 - - - Dátum valuty - 110001 - - - Predčíslo účtu - 110002 - - - Číslo účtu - 110003 - - - Predčíslo protiúčtu - 110004 - - - Číslo protiúčtu - 110005 - - - Kód banky protiúčtu - 110006 - - - Názov protiúčtu - 110007 - - - Suma - 110008 - - - Mena - 110009 - - - Kurz - 110010 - - - Zostatok - 110011 - - - Popis obratu - 110012 - - - E2E reference - 110013 - - - Variabilný symbol - 110014 - - - Konštantný symbol - 110015 - - - Špecifický symbol - 110016 - - - Poznámka - 110017 - - - Číslo výpisu - 110018 - - - Identifikácia protiúčtu 1 - 110019 - - - Identifikácia protiúčtu 2 - 110020 - - - Identifikácia protiúčtu 3 - 110021 - - - Identifikácia protiúčtu 4 - 110022 - - - Správa pre prijímateľa 1 - 110023 - - - Správa pre prijímateľa 2 - 110024 - - - Správa pre prijímateľa 3 - 110025 - - - Správa pre prijímateľa 4 - 110026 - - - - Dátum dojednania návrhu na uzavretie poistnej zmluvy - 309002 - - - - Ponuka PDF - 309003 - Automaticky generované - - - self: f.this; - generate "Insurance.offerPDF",always into self - - - - - Zmluva PDF - 309004 - Automaticky generované - - - self: f.this; - generate "Insurance.draftPDF",always into self - - - - - - - Dummy - 410001 - - - - Only Property - Only Household - Property and Household - - - - - - 2 - 260 - 300 - - home - 1 - auto - - 1 - - - 1 - - true - - - - 1 - - start - - 410001 - - forbidden - - trans: t.this; - changeCaseProperty "icon" about { trans.icon } - - - self: f.this; - change self about { "Nehnutelnost" } - - - - - - - - 4 - 180 - 900 - - weekend - 2 - auto - - 1 - - - 1 - - true - - - - 1 - - start - - 410001 - - forbidden - - trans: t.this; - changeCaseProperty "icon" about { trans.icon } - - - self: f.this; - change self about { "Domacnost" } - - - - - - - - 3 - 180 - 580 - - home weekend - 3 - auto - - 1 - - - 1 - - true - - - - 1 - - start - - 410001 - - forbidden - - trans: t.this; - changeCaseProperty "icon" about { trans.icon } - - - self: f.this; - change self about { "Nehnutelnost a domacnost" } - - - - - - - - 154 - 620 - 60 - - 1 - auto - - 2 - - - 1 - - true - - - - 1 - - start - - - 101001 - - editable - required - - - - - - 301005 - - editable - required - - - - - 101002 - - editable - required - - - - - 2 - - start - - - 101003 - - editable - required - - - - - 101004 - - editable - required - - - - - 101005 - - editable - required - - - - - 101006 - - editable - required - - - - - 101007 - - editable - required - - - - - 101008 - - editable - required - - - - - 101012 - - editable - required - - - - - 101014 - - editable - required - - - - - 101016 - - editable - required - - - - - - - 155 - 620 - 220 - - 2 - auto - - 2 - - - 1 - - true - - - - 2 - - start - - - 102001 - - required - editable - - - f1: f.102001, - f2: f.106001, - other: f.308005; - change other about { - return Boolean.logicalAnd(f1.value != null, f2.value != null); - } - - - - - other: f.410001, - field: f.this; - change field choices { - if (other.value == "Nehnutelnost") - return field.choices + ["rozostavaná stavba"]; - return field.choices; - } - - - - - - - 105005 - - editable - - - - - 102006 - - editable - required - - - - - 102007 - - editable - required - - - - - 107001 - - editable - required - - - - - 3 - - left - - - 105001 - - editable - required - - - - - 105002 - - editable - required - - - - - 105003 - - editable - required - - - - - 305001 - - visible - - - - - 102002 - - editable - - - - - 102003 - - hidden - - - - - 102004 - - editable - - - - - - - 414 - 620 - 380 - - 3 - auto - - 2 - - - 1 - - true - - - - 1 - - start - - - 105031 - - editable - - - field: f.this, - coeff: f.205018; - change coeff about { - if (field.value) - return 3.0 as Double; - return 0 as Double; - } - - - - - check: f.105031, - other: f.105032, - trans: t.414; - make other,editable on trans when { check.value } - - - - - check: f.105031, - other: f.105032, - trans: t.414; - make other,required on trans when { check.value } - - - - - check: f.105031, - other: f.105032, - trans: t.414; - make other,hidden on trans when { !check.value } - - - - - check: f.105031, - other: f.305015, - trans: t.414; - make other,visible on trans when { check.value } - - - - - check: f.105031, - other: f.305015, - trans: t.414; - make other,hidden on trans when { !check.value } - - - - - - check: f.105031, - other: f.105032; - change other about { null; } - - - - - check: f.105031, - other: f.105032; - change other about { null; } - - - - - - - 2 - - start - - - 105032 - - hidden - - - - - 305015 - - hidden - - - - - 3 - - start - - - 105033 - - editable - - - field: f.this, - coeff: f.205019; - change coeff about { - if (field.value) - return 5.0 as Double; - return 0 as Double; - } - - - - - check: f.105033, - other: f.105034, - trans: t.414; - make other,editable on trans when { check.value } - - - - - check: f.105033, - other: f.105034, - trans: t.414; - make other,required on trans when { check.value } - - - - - check: f.105033, - other: f.105034, - trans: t.414; - make other,hidden on trans when { !check.value } - - - - - check: f.105033, - other: f.305016, - trans: t.414; - make other,visible on trans when { check.value } - - - - - check: f.105033, - other: f.305016, - trans: t.414; - make other,hidden on trans when { !check.value } - - - - - - check: f.105033, - other: f.105034; - change other about { null; } - - - - - check: f.105033, - other: f.105034; - change other about { null; } - - - - - - - 4 - - start - - - 105034 - - hidden - - - - - 305016 - - hidden - - - - - 1 - - start - - - 105035 - - editable - - - isGarage: f.105035, - trans: t.414, - other: f.105004; - make other,editable on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.105004; - make other,required on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.105004; - make other,hidden on trans when { !isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.105008; - make other,editable on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.105008; - make other,hidden on trans when { !isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.105007; - make other,required on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.105007; - make other,hidden on trans when { !isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.305019; - make other,editable on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.305019; - make other,required on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.305019; - make other,hidden on trans when { !isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.305003; - make other,visible on trans when { isGarage.value } - - - - - isGarage: f.105035, - trans: t.414, - other: f.305003; - make other,hidden on trans when { !isGarage.value } - - - - - - - 101 - - start - - - 105004 - - hidden - - - - - 105008 - - hidden - - - - isGarage: f.105008, - trans: t.588, - other: f.109054; - make other,editable on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109055; - make other,editable on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109056; - make other,editable on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109057; - make other,editable on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109054; - make other,required on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109055; - make other,required on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109056; - make other,required on trans when { !isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109057; - make other,required on trans when { !isGarage.value } - - - - - - isGarage: f.105008, - trans: t.588, - other: f.109054; - make other,hidden on trans when { isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109055; - make other,hidden on trans when { isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109056; - make other,hidden on trans when { isGarage.value } - - - - - isGarage: f.105008, - trans: t.588, - other: f.109057; - make other,hidden on trans when { isGarage.value } - - - - - - - 105007 - - hidden - - - - - 305019 - - hidden - - - - - - 305003 - - hidden - - - - - - - 413 - 620 - 540 - - 4 - auto - - 2 - - - 1 - - true - - - - 2 - - start - - - 105009 - - editable - - - - idTrue: f.105009, - trans: t.413, - other: f.105010; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105009, - trans: t.413, - other: f.305004; - make other,visible on trans when { idTrue.value } - - - - - idTrue: f.105009, - trans: t.413, - other: f.105010; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105009, - trans: t.413, - other: f.305004; - make other,hidden on trans when { !idTrue.value } - - - - - - - 102 - - start - - - 105010 - - hidden - - - field: f.this, - check: f.105009, - exces: f.208001, - other: f.305004; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305004 - - hidden - - - - - 3 - - start - - - 105011 - - editable - - - - idTrue: f.105011, - trans: t.413, - other: f.105012; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105011, - trans: t.413, - other: f.105012; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105011, - trans: t.413, - other: f.305005; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105011, - trans: t.413, - other: f.105012; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105011, - trans: t.413, - other: f.305005; - make other,hidden on trans when { !idTrue.value } - - - - - - - 103 - - start - - - 105012 - - hidden - - - field: f.this, - check: f.105011, - exces: f.208001, - other: f.305005; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305005 - - hidden - - - - - 4 - - start - - - 105013 - - editable - - - - idTrue: f.105013, - trans: t.413, - other: f.105014; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105013, - trans: t.413, - other: f.305006; - make other,visible on trans when { idTrue.value } - - - - - idTrue: f.105013, - trans: t.413, - other: f.105014; - make other,required on trans when { idTrue.value } - - - - - - idTrue: f.105013, - trans: t.413, - other: f.105014; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105013, - trans: t.413, - other: f.305006; - make other,hidden on trans when { !idTrue.value } - - - - - - - 104 - - start - - - 105014 - - hidden - - - field: f.this, - check: f.105013, - exces: f.208001, - other: f.305006; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305006 - - hidden - - - - - 5 - - start - - - 105015 - - editable - - - - idTrue: f.105015, - trans: t.413, - other: f.105016; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105015, - trans: t.413, - other: f.105016; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105015, - trans: t.413, - other: f.305007; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105015, - trans: t.413, - other: f.105016; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105015, - trans: t.413, - other: f.305007; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105015, - other: f.105016; - change other about { null; } - - - - - idTrue: f.105015, - other: f.305007; - change other about { null; } - - - - - - - 105 - - start - - - 105016 - - hidden - - - field: f.this, - check: f.105015, - exces: f.208001, - other: f.305007; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305007 - - hidden - - - - - 6 - - start - - - - 105017 - - editable - - - - idTrue: f.105017, - trans: t.413, - other: f.105018; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105017, - trans: t.413, - other: f.105018; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105017, - trans: t.413, - other: f.305008; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105017, - trans: t.413, - other: f.105018; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105017, - trans: t.413, - other: f.305008; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105017, - other: f.105018; - change other about { null; } - - - - - idTrue: f.105017, - other: f.305008; - change other about { null; } - - - - - - - 106 - - start - - - 105018 - - hidden - - - field: f.this, - check: f.105017, - exces: f.208001, - other: f.305008; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305008 - - hidden - - - - - 7 - - start - - - 105019 - - editable - - - - idTrue: f.105019, - trans: t.413, - other: f.105020; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105019, - trans: t.413, - other: f.105020; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105019, - trans: t.413, - other: f.305009; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105019, - trans: t.413, - other: f.105020; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105019, - trans: t.413, - other: f.305009; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105019, - other: f.105020; - change other about { null; } - - - - - idTrue: f.105019, - other: f.305009; - change other about { null; } - - - - - - - 107 - - start - - - 105020 - - hidden - - - field: f.this, - check: f.105019, - exces: f.208001, - other: f.305009; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305009 - - hidden - - - - - 8 - - start - - - 105021 - - editable - - - - idTrue: f.105021, - trans: t.413, - other: f.105022; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105021, - trans: t.413, - other: f.105022; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105021, - trans: t.413, - other: f.305010; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105021, - trans: t.413, - other: f.105022; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105021, - trans: t.413, - other: f.305010; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105021, - other: f.105022; - change other about { null; } - - - - - idTrue: f.105021, - other: f.305010; - change other about { null; } - - - - - - - 108 - - start - - - 105022 - - hidden - - - field: f.this, - check: f.105021, - exces: f.208001, - other: f.305010; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305010 - - hidden - - - - - 9 - - start - - - 105023 - - editable - - - - idTrue: f.105023, - trans: t.413, - other: f.105024; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105023, - trans: t.413, - other: f.105024; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105023, - trans: t.413, - other: f.305011; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105023, - trans: t.413, - other: f.105024; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105023, - trans: t.413, - other: f.305011; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105023, - other: f.105024; - change other about { null; } - - - - - idTrue: f.105023, - other: f.305011; - change other about { null; } - - - - - - - 109 - - start - - - 105024 - - hidden - - - field: f.this, - check: f.105023, - exces: f.208001, - other: f.305011; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305011 - - hidden - - - - - 10 - - start - - - 105025 - - editable - - - - idTrue: f.105025, - trans: t.413, - other: f.105026; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105025, - trans: t.413, - other: f.105026; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105025, - trans: t.413, - other: f.305012; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105025, - trans: t.413, - other: f.105026; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105025, - trans: t.413, - other: f.305012; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105025, - other: f.105026; - change other about { null; } - - - - - idTrue: f.105025, - other: f.305012; - change other about { null; } - - - - - - - 110 - - start - - - 105026 - - hidden - - - field: f.this, - check: f.105025, - exces: f.208001, - other: f.305012; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305012 - - hidden - - - - - 11 - - start - - - 105027 - - editable - - - - idTrue: f.105027, - trans: t.413, - other: f.105028; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105027, - trans: t.413, - other: f.105028; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105027, - trans: t.413, - other: f.305013; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105027, - trans: t.413, - other: f.105028; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105027, - trans: t.413, - other: f.305013; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105027, - other: f.105028; - change other about { null; } - - - - - idTrue: f.105027, - other: f.305013; - change other about { null; } - - - - - - - 111 - - start - - - 105028 - - hidden - - field: f.this, - check: f.105027, - exces: f.208001, - other: f.305013; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305013 - - hidden - - - - - 12 - - start - - - 105029 - - editable - - - - idTrue: f.105029, - trans: t.413, - other: f.105030; - make other,editable on trans when { idTrue.value } - - - - - idTrue: f.105029, - trans: t.413, - other: f.105030; - make other,required on trans when { idTrue.value } - - - - - idTrue: f.105029, - trans: t.413, - other: f.305014; - make other,visible on trans when { idTrue.value } - - - - - - idTrue: f.105029, - trans: t.413, - other: f.105030; - make other,hidden on trans when { !idTrue.value } - - - - - idTrue: f.105029, - trans: t.413, - other: f.305014; - make other,hidden on trans when { !idTrue.value } - - - - - - idTrue: f.105029, - other: f.105030; - change other about { null; } - - - - - idTrue: f.105029, - other: f.305014; - change other about { null; } - - - - - - - 112 - - start - - - 105030 - - hidden - - field: f.this, - check: f.105029, - exces: f.208001, - other: f.305014; - change other about { - if (check.value) - return ((field.value*exces.value)/1000.0) as Double; - return other.value as Double; - } - - - - - - - 305014 - - hidden - - - - - 2 - - - - 305017 - - visible - - - - - 305018 - - visible - - - - - - - 363 - 620 - 700 - - 5 - auto - - 2 - - - 1 - - true - - - - 5 - - start - - - 103001 - - editable - required - - - - - 106001 - - editable - required - - - - - 5 - - start - - - 107003 - - editable - required - - - - - 104003 - - hidden - - - - - 6 - - start - - - 103002 - - editable - required - - - - - 106003 - - editable - required - - - - - 5 - - start - true - - - 103004 - - editable - required - - - - - 5 - - start - true - - - 103005 - - editable - required - - - - - - - 421 - 620 - 860 - - 6 - auto - - 2 - - - 1 - - true - - - - 1 - - start - - - 106004 - - editable - - - idTrue: f.106004, - trans: t.421, - other: f.106005; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106004, - trans: t.421, - other: f.106005; - make other,required on trans when { idTrue.value } - - - idTrue: f.106004, - trans: t.421, - other: f.306002; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106004, - trans: t.421, - other: f.106005; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106004, - trans: t.421, - other: f.306002; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106004, - other: f.106005; - change other about { null; } - - - idTrue: f.106004, - other: f.306002; - change other about { null; } - - - - - - 2 - - start - - - 106005 - - hidden - - field: f.this, - check: f.106004, - exces: f.208002, - other: f.306002; - change other about { - if (check.value) - return ((field.value*exces.value*4.2)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306002 - - hidden - - - - - 3 - - start - - - 106006 - - editable - - - idTrue: f.106006, - trans: t.421, - other: f.106007; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106006, - trans: t.421, - other: f.106007; - make other,required on trans when { idTrue.value } - - - idTrue: f.106006, - trans: t.421, - other: f.306003; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106006, - trans: t.421, - other: f.106007; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106006, - trans: t.421, - other: f.306003; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106006, - other: f.106007; - change other about { null; } - - - idTrue: f.106006, - other: f.306003; - change other about { null; } - - - - - - 4 - - start - - - 106007 - - hidden - - field: f.this, - check: f.106006, - exces: f.208002, - other: f.306003; - change other about { - if (check.value) - return ((field.value*exces.value*4.2)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306003 - - hidden - - - - - 5 - - start - - - 106008 - - editable - - - idTrue: f.106008, - trans: t.421, - other: f.106009; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106008, - trans: t.421, - other: f.106009; - make other,required on trans when { idTrue.value } - - - idTrue: f.106008, - trans: t.421, - other: f.306004; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106008, - trans: t.421, - other: f.106009; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106008, - trans: t.421, - other: f.306004; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106008, - other: f.106009; - change other about { null; } - - - idTrue: f.106008, - other: f.306004; - change other about { null; } - - - - - - 6 - - start - - - 106009 - - hidden - - field: f.this, - check: f.106008, - exces: f.208002, - other: f.306004; - change other about { - if (check.value) - return ((field.value*exces.value*4.2)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306004 - - hidden - - - - - 7 - - start - - - 106010 - - editable - - - idTrue: f.106010, - trans: t.421, - other: f.106011; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106010, - trans: t.421, - other: f.106011; - make other,required on trans when { idTrue.value } - - - idTrue: f.106010, - trans: t.421, - other: f.306005; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106010, - trans: t.421, - other: f.106011; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106010, - trans: t.421, - other: f.306005; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106010, - other: f.106011; - change other about { null; } - - - idTrue: f.106010, - other: f.306005; - change other about { null; } - - - - - - 8 - - start - - - 106011 - - hidden - - field: f.this, - check: f.106010, - exces: f.208002, - other: f.306005; - change other about { - if (check.value) - return ((field.value*exces.value*25.0)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306005 - - hidden - - - - - 9 - - start - - - 106012 - - editable - - - idTrue: f.106012, - trans: t.421, - other: f.106013; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106012, - trans: t.421, - other: f.106013; - make other,required on trans when { idTrue.value } - - - idTrue: f.106012, - trans: t.421, - other: f.306006; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106012, - trans: t.421, - other: f.106013; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106012, - trans: t.421, - other: f.306006; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106012, - other: f.106013; - change other about { null; } - - - idTrue: f.106012, - other: f.306006; - change other about { null; } - - - - - - 10 - - start - - - 106013 - - hidden - - field: f.this, - check: f.106012, - exces: f.208002, - other: f.306006; - change other about { - if (check.value) - return ((field.value*exces.value*15.0)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306006 - - hidden - - - - - 11 - - start - - - 106014 - - editable - - - idTrue: f.106014, - trans: t.421, - other: f.106015; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106014, - trans: t.421, - other: f.106015; - make other,required on trans when { idTrue.value } - - - idTrue: f.106014, - trans: t.421, - other: f.306007; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106014, - trans: t.421, - other: f.106015; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106014, - trans: t.421, - other: f.306007; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106014, - other: f.106015; - change other about { null; } - - - idTrue: f.106014, - other: f.306007; - change other about { null; } - - - - - - 12 - - start - - - 106015 - - hidden - - field: f.this, - check: f.106014, - exces: f.208002, - other: f.306007; - change other about { - if (check.value) - return ((field.value*exces.value*50.0)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306007 - - hidden - - - - - 13 - - start - - - 106016 - - editable - - - idTrue: f.106016, - trans: t.421, - other: f.106017; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106016, - trans: t.421, - other: f.106017; - make other,required on trans when { idTrue.value } - - - idTrue: f.106016, - trans: t.421, - other: f.306008; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106016, - trans: t.421, - other: f.106017; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106016, - trans: t.421, - other: f.306008; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106016, - other: f.106017; - change other about { null; } - - - idTrue: f.106016, - other: f.306008; - change other about { null; } - - - - - - 14 - - start - - - 106017 - - hidden - - field: f.this, - check: f.106016, - exces: f.208002, - other: f.306008; - change other about { - if (check.value) - return ((field.value*exces.value*3.5)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306008 - - hidden - - - - - 15 - - start - - - 106018 - - editable - - - idTrue: f.106018, - trans: t.421, - other: f.106019; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106018, - trans: t.421, - other: f.106019; - make other,required on trans when { idTrue.value } - - - idTrue: f.106018, - trans: t.421, - other: f.306009; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106018, - trans: t.421, - other: f.106019; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106018, - trans: t.421, - other: f.306009; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106018, - other: f.106019; - change other about { null; } - - - idTrue: f.106018, - other: f.306009; - change other about { null; } - - - - - - 16 - - start - - - 106019 - - hidden - - field: f.this, - check: f.106018, - exces: f.208002, - other: f.306009; - change other about { - if (check.value) - return ((field.value*exces.value*7.0)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306009 - - hidden - - - - - 17 - - start - - - 106020 - - editable - - - idTrue: f.106020, - trans: t.421, - other: f.106021; - make other,editable on trans when { idTrue.value } - - - idTrue: f.106020, - trans: t.421, - other: f.106021; - make other,required on trans when { idTrue.value } - - - idTrue: f.106020, - trans: t.421, - other: f.306010; - make other,visible on trans when { idTrue.value } - - - - idTrue: f.106020, - trans: t.421, - other: f.106021; - make other,hidden on trans when { !idTrue.value } - - - idTrue: f.106020, - trans: t.421, - other: f.306010; - make other,hidden on trans when { !idTrue.value } - - - - idTrue: f.106020, - other: f.106021; - change other about { null; } - - - idTrue: f.106020, - other: f.306010; - change other about { null; } - - - - - - 18 - - start - - - 106021 - - hidden - - field: f.this, - check: f.106020, - exces: f.208002, - other: f.306010; - change other about { - if (check.value) - return ((field.value*exces.value*10.0)/1000.0) as Double; - return other.value as Double; - } - - - - - - 306010 - - hidden - - - - - 19 - - start - - - 106024 - - visible - - - - 106025 - - visible - - - - - - - 364 - 620 - 1020 - - 7 - auto - - 2 - - - 1 - - true - - - - 1 - Nehnuteľnosť - start - - - 105006 - - hidden - - - - - 105036 - - hidden - - - - - 305002 - - hidden - - - - - 308001 - - hidden - - - - - 2 - Domácnosť - start - - - 106002 - - hidden - - - - - 106022 - - hidden - - - - - 106023 - - hidden - - - - - 306001 - - hidden - - - - - 308002 - - hidden - - - - - 3 - Poistenie zodpovednosti - start - - - 308008 - - hidden - - - - - 308009 - - hidden - - - - - 308003 - - hidden - - - - - 4 - Sumarizácia poistnej sumy - start - true - - - 308004 - - visible - - - - - 5 - - start - true - - - 108001 - - editable - required - - - - - 2 - - start - true - - - 308005 - - visible - - - - - 2 - - start - true - - - 108002 - - editable - required - - - - - 2 - - start - true - - - 108005 - - hidden - - - - - 2 - - start - true - - - 108003 - - editable - - - - - 2 - - start - true - - - 108004 - - editable - - - - - 2 - - start - true - - - 308006 - - visible - - - - - 2 - - start - true - - - 308010 - - visible - - - - - 3 - start - false - - 309001 - - hidden - - - self: f.this; - generate "Insurance.offerId",once into self - - - - - - 309003 - - visible - - - - - - - 588 - 620 - 1180 - - 8 - auto - - 2 - - - 1 - - true - - - - - 1 - Poistník - start - - - - 109007 - - editable - - - - - 109058 - - hidden - - - - - 109012 - - hidden - - - - - 109061 - - hidden - - - - - 109062 - - hidden - - - - - 109008 - - editable - - - - - 109009 - - editable - - - - - 109010 - - editable - required - - - - - 109011 - - editable - required - - - - - 109016 - - editable - required - - - - - 109017 - - editable - required - - - - - 109013 - - editable - required - - - - - 109014 - - editable - required - - - - - 109015 - - editable - required - - - - - 109018 - - editable - - - - - 109019 - - editable - - - - - 2 - Poistený - - - 109020 - - editable - - - - - - 109021 - - hidden - - - - - 109059 - - hidden - - - - - 109026 - - hidden - - - - - 109063 - - hidden - - - - - 109064 - - hidden - - - - - 109022 - - hidden - - - - - 109023 - - hidden - - - - - 109024 - - hidden - - - - - 109025 - - hidden - - - - - 109030 - - hidden - - - - - 109031 - - hidden - - - - - 109027 - - hidden - - - - - 109028 - - hidden - - - - - 109029 - - hidden - - - - - 109032 - - hidden - - - - - 109033 - - hidden - - - - - 5 - Miesto poistenia - start - - - 109045 - - editable - required - - - - 109046 - - editable - required - - - - 109047 - - editable - required - - - - 109048 - - editable - required - - - - - 3 - Adresa trvalého pobytu - - - 109035 - - editable - - - - - 9 - - - 109036 - - hidden - - - - 109037 - - hidden - - - - 109038 - - hidden - - - - 109039 - - hidden - - - - - 4 - Korešpondenčná adresa - start - - - - 109034 - - editable - - - - - 7 - - start - - 109041 - - hidden - - - - 109042 - - hidden - - - - 109043 - - hidden - - - - 109044 - - hidden - - - - - 6 - Adresa garáže - - - 109054 - - hidden - - - - 109055 - - hidden - - - - 109056 - - hidden - - - - 109057 - - hidden - - - - - - - - - - 1618 - 1180 - 260 - - 9 - auto - - 3 - - - 1 - - true - - - - 1 - start - - - 309001 - - visible - - - - - 109001 - - editable - - - - - 109002 - - hidden - - - - - 109003 - - hidden - - - - 109004 - - editable - - - - - 109005 - - editable - - - - - 109060 - - editable - - - - - 109006 - - required - editable - - - - - 109065 - - hidden - - - - - 109066 - - editable - - - - - 109067 - - editable - - - - - 309004 - - visible - - - - - - - 1661 - 1185 - 898 - - 9 - auto - - 3 - - - 1 - - true - - - - 1 - start - - - 309001 - - visible - - - - - 109001 - - required - editable - - - - - 109002 - - hidden - - - - - 109003 - - hidden - - - - 109004 - - editable - - - - - 109005 - - editable - - - - - 109060 - - editable - - - - - 109006 - - required - editable - - - - - 109065 - - hidden - - - - - 109066 - - editable - - - - - 109067 - - editable - - - - - 309004 - - visible - - - - - - - 332 - 1180 - 580 - - 9 - auto - - 3 - - - 1 - - true - - - - 1 - start - - - 309001 - - visible - - - - - 109001 - - required - editable - - - - - 109002 - - hidden - - - - - 109003 - - hidden - - - - 109004 - - editable - - - - - 109005 - - editable - - - - - 109060 - - editable - - - - - 109006 - - required - editable - - - - - 109065 - - hidden - - - - - 109066 - - editable - - - - - 109067 - - editable - - - - - 309004 - - visible - - - - - - - - - - 674 - 1433 - 965 - - 11 - - 3 - - - - - 687 - 1431 - 1243 - - 12 - - 3 - - - - - - - - 680 - 1681 - 967 - - 12 - - 3 - - - 2 - - true - - - - 1 - Informačné údaje - start - - - - 309001 - - forbidden - immediate - - - - - 109010 - - visible - immediate - - - - - 109011 - - visible - immediate - - - - - 109001 - - visible - immediate - - - - - - 2 - Údaje o platbe - start - - - 110001 - - editable - - - - - 110002 - - editable - - - - - 110003 - - required - editable - - - - - 110004 - - editable - - - - - 110005 - - editable - - - - - 110006 - - editable - - - - - 110007 - - editable - - - - - 110008 - - required - editable - - - - - 110009 - - required - editable - - - - - 110010 - - editable - - - - - 110011 - - required - editable - - - - - 110012 - - editable - - - - - 110013 - - editable - - - - - 110014 - - editable - - - - - 110015 - - editable - - - - - 110016 - - editable - - - - - 110017 - - editable - - - - - 110018 - - editable - - - - - 110019 - - editable - - - - - 110020 - - editable - - - - - 110021 - - editable - - - - - 110022 - - editable - - - - - 110023 - - editable - - - - - 110024 - - editable - - - - - 110025 - - editable - - - - - 110026 - - editable - - - - - - - 686 - 1870 - 1071 - - 13 - - 3 - - - - - 692 - 1682 - 1250 - - 14 - - 3 - - - - - 694 - 2077 - 1245 - - 15 - - 3 - - - - - - - - 2015 - 2229 - 38 - - 1 - - 3 - - - 1 - - true - - - - 1 - - start - - - 301005 - - visible - - - - - 101001 - - visible - - - - - 301002 - - visible - - - - 101002 - - visible - - - - - 2 - - start - true - - - 101003 - - visible - - - - - 3 - - true - - - 101004 - - visible - - - - - 4 - - true - - - 101005 - - visible - - - - - 101006 - - visible - - - - - 101007 - - visible - - - - - 101008 - - visible - - - - - 101008 - - visible - - - - - 8 - - true - - - 101012 - - visible - - - - - 101014 - - visible - - - - - 101016 - - visible - - - - - - - 2019 - 2231 - 143 - - 2 - - 3 - - - 1 - - true - - - - 2 - - start - - - 102001 - - visible - - - - - 105001 - - visible - - - - - 105002 - - visible - - - - - 105003 - - visible - - - - - 105004 - - visible - - - - - 305001 - - visible - - - - - 102002 - - visible - - - - - 102003 - - visible - - - - - 102004 - - visible - - - - - 102006 - - visible - - - - - 102007 - - visible - - - - - 3 - - left - - - 107001 - - visible - - - - - - - 2020 - 2233 - 247 - - 3 - - 3 - - - 1 - - true - - - - 1 - - - - 105031 - - visible - - - - - 105032 - - visible - - - - - 305015 - - visible - - - - - 105033 - - visible - - - - - 105034 - - visible - - - - - 305016 - - visible - - - - - - - 2021 - 2233 - 351 - - 4 - - 3 - - - 1 - - true - - - - 1 - - - - 105035 - - visible - - - - - 105007 - - visible - - - - - 105008 - - visible - - - - - 305019 - - visible - - - - - 305003 - - visible - - - - - 105009 - - visible - - - - - 105010 - - visible - - - - - 305004 - - visible - - - - - 105011 - - visible - - - - - 105012 - - visible - - - - - 305005 - - visible - - - - - 105013 - - visible - - - - - 105014 - - visible - - - - - 305006 - - visible - - - - - 105015 - - visible - - - - - 105016 - - visible - - - - - 305007 - - visible - - - - - 105017 - - visible - - - - - 105018 - - visible - - - - - 305008 - - visible - - - - - 105019 - - visible - - - - - 105020 - - visible - - - - - 305009 - - visible - - - - - 105021 - - visible - - - - - 105022 - - visible - - - - - 305010 - - visible - - - - - 105023 - - visible - - - - - 105024 - - visible - - - - - 305011 - - visible - - - - - 105025 - - visible - - - - - 105026 - - visible - - - - - 305012 - - visible - - - - - 105027 - - visible - - - - - 105028 - - visible - - - - - 305013 - - visible - - - - - 105029 - - visible - - - - - 105030 - - visible - - - - - 305014 - - visible - - - - - 2 - - - - 305017 - - visible - - - - - 305018 - - visible - - - - - - - 2018 - 2231 - 451 - - 5 - - 3 - - - 1 - - true - - - - 1 - - - - 103001 - - visible - - - - - 106003 - - visible - - - - - 103002 - - visible - - - - - 103004 - - visible - - - - - 103005 - - visible - - - - - - - 2729 - 2227 - 1021 - - 7 - - 2 - - - 1 - - true - - - - 1 - Nehnuteľnosť - start - - - 105006 - - visible - - - - - 105036 - - visible - - - - - 305002 - - visible - - - - - 308001 - - visible - - - - - 2 - Domácnosť - start - - - 106002 - - visible - - - - - 106022 - - visible - - - - - 106023 - - visible - - - - - 306001 - - visible - - - - - 308002 - - visible - - - - - 3 - Poistenie zodpovednosti - start - - - 308008 - - visible - - - - - 308009 - - visible - - - - - 308003 - - visible - - - - - 4 - Sumarizácia poistnej sumy - start - true - - - 308004 - - visible - - - - - 5 - - start - true - - - 108001 - - visible - - - - - 2 - - start - true - - - 308005 - - visible - - - - - 2 - - start - true - - - 108002 - - visible - - - - - 2 - - start - true - - - 108005 - - visible - - - - - 2 - - start - true - - - 108003 - - visible - - - - - 2 - - start - true - - - 108004 - - visible - - - - - 2 - - start - true - - - 308006 - - visible - - - - - 2 - - start - true - - - 308010 - - visible - - - - - 3 - start - false - - 309001 - - visible - - - self: f.this; - generate "Insurance.offerId",once into self - - - - - - 309003 - - visible - - - - - - - 2017 - 2233 - 549 - - 6 - - 3 - - - 1 - - true - - - - 1 - - - - 106004 - - visible - - - - - 106005 - - visible - - - - - 306002 - - visible - - - - - 106006 - - visible - - - - - 106007 - - visible - - - - - 306003 - - visible - - - - - 106008 - - visible - - - - - 106009 - - visible - - - - - 306004 - - visible - - - - - 106010 - - visible - - - - - 106011 - - visible - - - - - 306005 - - visible - - - - - 106012 - - visible - - - - - 106013 - - visible - - - - - 306006 - - visible - - - - - 106014 - - visible - - - - - 106015 - - visible - - - - - 306007 - - visible - - - - - 106016 - - visible - - - - - 106017 - - visible - - - - - 306008 - - visible - - - - - 106018 - - visible - - - - - 106019 - - visible - - - - - 306009 - - visible - - - - - 106020 - - visible - - - - - 106021 - - visible - - - - - 306010 - - visible - - - - - - - 2016 - 2235 - 646 - - 7 - - 3 - - - 1 - - true - - - - 1 - - - - - 109007 - - visible - - - - - 109008 - - visible - - - - - 109009 - - visible - - - - - 109010 - - visible - - - - - 109011 - - visible - - - - - 109012 - - visible - - - - - 109013 - - visible - - - - - 109014 - - visible - - - - - 109015 - - visible - - - - - 109016 - - visible - - - - - 109017 - - visible - - - - - 109018 - - visible - - - - - 109019 - - visible - - - - - 109020 - - visible - - - - - - 109021 - - hidden - - - - - 109022 - - hidden - - - - - 109023 - - hidden - - - - - 109024 - - hidden - - - - - 109025 - - hidden - - - - - 109026 - - hidden - - - - - 109027 - - hidden - - - - - 109028 - - hidden - - - - - 109029 - - hidden - - - - - 109030 - - hidden - - - - - 109031 - - hidden - - - - - 109032 - - hidden - - - - - 109033 - - hidden - - - - - - 109036 - - - visible - - - - 109037 - - - visible - - - - 109038 - - - visible - - - - 109039 - - - visible - - - - - 109041 - - visible - - - - 109042 - - visible - - - - 109043 - - visible - - - - 109044 - - visible - - - - - 109045 - - - visible - - - - 109046 - - - visible - - - - 109047 - - - visible - - - - 109048 - - - visible - - - - - 109054 - - - visible - - - - 109055 - - - visible - - - - 109056 - - - visible - - - - 109057 - - - visible - - - - - - - 2014 - 2237 - 743 - - 8 - - 3 - - - 1 - - true - - - - 1 - - - - 309001 - - visible - - - - - 109001 - - visible - - - - - 109002 - - visible - - - - - 109003 - - visible - - - - 109004 - - visible - - - - - 109005 - - visible - - - - - 109006 - - visible - - - - - 309004 - - visible - - - - - - - 2045 - 2237 - 841 - - 9 - - 3 - - - 1 - - true - - - - 1 - - - - 308007 - - visible - - - - - - - 2046 - 2237 - 929 - - 10 - - 3 - - - 1 - - true - - - - - - 2484 - 1457 - 117 - - - - 1 - - - 410001 - - hidden - - - self: f.this; - generate "Insurance.sendMail",always into self - - - - - - - - - 1 - 20 - 580 - - 1 - false - - - 398 - 420 - 60 - - 0 - false - - - 399 - 420 - 220 - - 0 - false - - - 400 - 420 - 700 - - 0 - false - - - 402 - 420 - 1020 - - 0 - false - - - 415 - 420 - 540 - - 0 - false - - - 416 - 420 - 380 - - 0 - false - - - 422 - 420 - 860 - - 0 - false - - - 444 - 860 - 60 - - 0 - false - - - 445 - 860 - 220 - - 0 - false - - - 446 - 900 - 700 - - 0 - false - - - 589 - 420 - 1180 - - 0 - false - - - 594 - 900 - 1180 - - 0 - false - - - 633 - 260 - 60 - - 0 - false - - - 672 - 1530 - 585 - - 0 - false - - - 682 - 1681 - 1070 - - 0 - false - - - 683 - 1430 - 1071 - - 0 - false - - - 693 - 1862 - 1249 - - 0 - false - - - 1368 - 900 - 380 - - 0 - false - - - 1369 - 900 - 540 - - 0 - false - - - 1372 - 900 - 860 - - 0 - false - - - 1393 - 900 - 1020 - - 0 - false - - - 1601 - 540 - 300 - - 0 - false - - - 1607 - 540 - 460 - - 0 - false - - - 1612 - 540 - 140 - - 0 - false - - - 1626 - 540 - 620 - - 0 - false - - - 1668 - 180 - 140 - - 0 - false - - - 1673 - 540 - 940 - - 0 - false - - - 1677 - 540 - 780 - - 0 - false - - - 1689 - 540 - 1100 - - 0 - false - - - 1851 - 180 - 1180 - - 0 - false - - - 2047 - 2063 - 43 - - 0 - false - - - 2048 - 2069 - 146 - - 0 - false - - - 2049 - 2069 - 250 - - 0 - false - - - 2050 - 2071 - 350 - - 0 - false - - - 2051 - 2065 - 450 - - 0 - false - - - 2052 - 2069 - 554 - - 0 - false - - - 2053 - 2071 - 651 - - 0 - false - - - 2054 - 2073 - 746 - - 0 - false - - - 2055 - 2073 - 837 - - 0 - false - - - 2056 - 2070 - 927 - - 0 - false - - - 2280 - 715 - 615 - - 0 - false - - - 2284 - 782 - 931 - - 0 - false - - - 2480 - 1399 - 117 - - 0 - false - - - 2728 - 2067 - 1013 - - 0 - false - - - - 7 - regular - 1 - 2 - 1 - - - 9 - regular - 1 - 3 - 1 - - - 12 - regular - 1 - 4 - 1 - - - 403 - regular - 398 - 154 - 1 - - - 404 - regular - 154 - 398 - 1 - - - 405 - regular - 399 - 155 - 1 - - - 406 - regular - 155 - 399 - 1 - - - 407 - regular - 400 - 363 - 1 - - - 408 - regular - 363 - 400 - 1 - - - 411 - regular - 402 - 364 - 1 - - - 412 - regular - 364 - 402 - 1 - - - 417 - regular - 415 - 413 - 1 - - - 418 - regular - 413 - 415 - 1 - - - 419 - regular - 416 - 414 - 1 - - - 420 - regular - 414 - 416 - 1 - - - 423 - regular - 422 - 421 - 1 - - - 424 - regular - 421 - 422 - 1 - - - 425 - regular - 2 - 398 - 1 - - - 426 - regular - 3 - 398 - 1 - - - 427 - regular - 4 - 398 - 1 - - - 428 - regular - 2 - 399 - 1 - - - 429 - regular - 3 - 399 - 1 - - - 430 - regular - 3 - 400 - 1 - - - 431 - regular - 4 - 400 - 1 - - - 435 - regular - 3 - 402 - 1 - - - 436 - regular - 4 - 402 - 1 - - - 437 - regular - 2 - 402 - 1 - - - 439 - regular - 3 - 415 - 1 - - - 441 - regular - 3 - 416 - 1 - - - 442 - regular - 4 - 422 - 1 - - - 443 - regular - 3 - 422 - 1 - - - 452 - regular - 154 - 444 - 1 - - - 453 - regular - 155 - 445 - 1 - - - 454 - regular - 363 - 446 - 1 - - - 514 - regular - 402 - 332 - 1 - - - 516 - regular - 400 - 332 - 1 - - - 517 - regular - 422 - 332 - 1 - - - 535 - regular - 446 - 332 - 1 - - - 591 - regular - 589 - 588 - 1 - - - 592 - regular - 588 - 589 - 1 - - - 595 - regular - 588 - 594 - 1 - - - 634 - regular - 2 - 633 - 1 - - - 677 - regular - 672 - 674 - 1 - - - 681 - regular - 672 - 680 - 1 - - - 684 - regular - 674 - 683 - 1 - - - 685 - regular - 680 - 682 - 1 - - - 688 - regular - 683 - 687 - 1 - - - 689 - regular - 687 - 683 - 1 - - - 690 - regular - 682 - 686 - 1 - - - 691 - regular - 686 - 682 - 1 - - - 695 - regular - 682 - 692 - 1 - - - 696 - regular - 692 - 693 - 1 - - - 697 - regular - 693 - 694 - 1 - - - 698 - regular - 694 - 693 - 1 - - - 1373 - regular - 414 - 1368 - 1 - - - 1374 - regular - 413 - 1369 - 1 - - - 1394 - regular - 364 - 1393 - 1 - - - 1397 - regular - 421 - 1372 - 1 - - - 1400 - regular - 1372 - 332 - 1 - - - 1595 - regular - 445 - 332 - 1 - - - 1596 - reset - 445 - 155 - 1 - - - 1599 - reset - 1368 - 414 - 1 - - - 1600 - reset - 1369 - 413 - 1 - - - 1602 - regular - 155 - 1601 - 1 - - - 1603 - regular - 1601 - 414 - 1 - - - 1604 - regular - 414 - 1601 - 1 - - - 1605 - regular - 2 - 416 - 1 - - - 1606 - regular - 2 - 415 - 1 - - - 1608 - regular - 414 - 1607 - 1 - - - 1609 - regular - 1607 - 413 - 1 - - - 1610 - regular - 413 - 1607 - 1 - - - 1611 - regular - 444 - 332 - 1 - - - 1613 - regular - 154 - 1612 - 1 - - - 1614 - regular - 1612 - 155 - 1 - - - 1615 - regular - 155 - 1612 - 1 - - - 1616 - regular - 1368 - 332 - 1 - - - 1617 - regular - 1369 - 332 - 1 - - - 1619 - regular - 444 - 1618 - 1 - - - 1620 - regular - 445 - 1618 - 1 - - - 1621 - regular - 1368 - 1618 - 1 - - - 1622 - regular - 1369 - 1618 - 1 - - - 1623 - regular - 1393 - 1618 - 1 - - - 1625 - regular - 594 - 1618 - 1 - - - 1627 - regular - 413 - 1626 - 1 - - - 1630 - reset - 444 - 154 - 1 - - - 1640 - regular - 2 - 589 - 1 - - - 1641 - regular - 398 - 1618 - 1 - - - 1642 - regular - 399 - 1618 - 1 - - - 1643 - regular - 416 - 1618 - 1 - - - 1644 - regular - 415 - 1618 - 1 - - - 1645 - regular - 633 - 1618 - 1 - - - 1646 - regular - 402 - 1618 - 1 - - - 1648 - regular - 589 - 1618 - 1 - - - 1649 - reset - 1393 - 364 - 1 - - - 1651 - reset - 594 - 588 - 1 - - - 1657 - regular - 332 - 672 - 1 - - - 1660 - regular - 1618 - 672 - 1 - - - 1662 - regular - 3 - 589 - 1 - - - 1669 - regular - 3 - 1668 - 1 - - - 1670 - regular - 2 - 1668 - 1 - - - 1671 - regular - 1668 - 155 - 1 - - - 1672 - regular - 155 - 1668 - 1 - - - 1674 - regular - 2 - 1673 - 1 - - - 1675 - regular - 1673 - 364 - 1 - - - 1676 - regular - 364 - 1673 - 1 - - - 1678 - regular - 363 - 1677 - 1 - - - 1679 - regular - 1677 - 421 - 1 - - - 1680 - regular - 421 - 1677 - 1 - - - 1685 - regular - 421 - 1673 - 1 - - - 1686 - regular - 1626 - 363 - 1 - - - 1687 - regular - 363 - 1626 - 1 - - - 1688 - regular - 4 - 1626 - 1 - - - 1690 - regular - 364 - 1689 - 1 - - - 1691 - regular - 1689 - 588 - 1 - - - 1692 - regular - 588 - 1689 - 1 - - - 1693 - regular - 1393 - 332 - 1 - - - 1694 - regular - 594 - 332 - 1 - - - 1696 - reset - 446 - 363 - 1 - - - 1697 - reset - 1372 - 421 - 1 - - - 1698 - regular - 589 - 332 - 1 - - - 1702 - regular - 4 - 589 - 1 - - - 1704 - regular - 444 - 1661 - 1 - - - 1705 - regular - 446 - 1661 - 1 - - - 1706 - regular - 1372 - 1661 - 1 - - - 1707 - regular - 1393 - 1661 - 1 - - - 1708 - regular - 594 - 1661 - 1 - - - 1710 - regular - 398 - 1661 - 1 - - - 1711 - regular - 400 - 1661 - 1 - - - 1712 - regular - 422 - 1661 - 1 - - - 1713 - regular - 402 - 1661 - 1 - - - 1714 - regular - 589 - 1661 - 1 - - - 1716 - regular - 1661 - 672 - 1 - - - 1852 - regular - 4 - 1851 - 1 - - - 1853 - regular - 1851 - 1661 - 1 - - - 2010 - regular - 398 - 332 - 1 - - - 2011 - regular - 399 - 332 - 1 - - - 2012 - regular - 416 - 332 - 1 - - - 2013 - regular - 415 - 332 - 1 - - - 2057 - regular - 1618 - 2047 - 1 - - - 2058 - regular - 1618 - 2048 - 1 - - - 2059 - regular - 1618 - 2049 - 1 - - - 2060 - regular - 1618 - 2050 - 1 - - - 2061 - regular - 1618 - 2051 - 1 - - - 2062 - regular - 1618 - 2052 - 1 - - - 2063 - regular - 1618 - 2053 - 1 - - - 2064 - regular - 1618 - 2054 - 1 - - - 2065 - regular - 1618 - 2055 - 1 - - - 2066 - regular - 1618 - 2056 - 1 - - - 2067 - regular - 1661 - 2056 - 1 - - - 2068 - regular - 1661 - 2055 - 1 - - - 2069 - regular - 1661 - 2054 - 1 - - - 2070 - regular - 1661 - 2053 - 1 - - - 2071 - regular - 1661 - 2052 - 1 - - - 2072 - regular - 1661 - 2051 - 1 - - - 2073 - regular - 1661 - 2050 - 1 - - - 2074 - regular - 1661 - 2049 - 1 - - - 2075 - regular - 1661 - 2048 - 1 - - - 2076 - regular - 1661 - 2047 - 1 - - - 2077 - regular - 2047 - 2015 - 1 - - - 2078 - regular - 2015 - 2047 - 1 - - - 2079 - regular - 2048 - 2019 - 1 - - - 2080 - regular - 2019 - 2048 - 1 - - - 2081 - regular - 2049 - 2020 - 1 - - - 2082 - regular - 2020 - 2049 - 1 - - - 2083 - regular - 2050 - 2021 - 1 - - - 2084 - regular - 2021 - 2050 - 1 - - - 2085 - regular - 2051 - 2018 - 1 - - - 2086 - regular - 2018 - 2051 - 1 - - - 2087 - regular - 2052 - 2017 - 1 - - - 2088 - regular - 2017 - 2052 - 1 - - - 2089 - regular - 2053 - 2016 - 1 - - - 2090 - regular - 2016 - 2053 - 1 - - - 2091 - regular - 2054 - 2014 - 1 - - - 2092 - regular - 2014 - 2054 - 1 - - - 2093 - regular - 2055 - 2045 - 1 - - - 2094 - regular - 2045 - 2055 - 1 - - - 2095 - regular - 2056 - 2046 - 1 - - - 2096 - regular - 2046 - 2056 - 1 - - - 2097 - regular - 332 - 2047 - 1 - - - 2098 - regular - 332 - 2048 - 1 - - - 2099 - regular - 332 - 2049 - 1 - - - 2100 - regular - 332 - 2050 - 1 - - - 2101 - regular - 332 - 2051 - 1 - - - 2102 - regular - 332 - 2052 - 1 - - - 2103 - regular - 332 - 2053 - 1 - - - 2104 - regular - 332 - 2054 - 1 - - - 2105 - regular - 332 - 2055 - 1 - - - 2106 - regular - 332 - 2056 - 1 - - - 2281 - regular - 154 - 2280 - 1 - - - 2282 - regular - 2280 - 363 - 1 - - - 2283 - regular - 363 - 2280 - 1 - - - 2285 - regular - 413 - 2284 - 1 - - - 2286 - regular - 2284 - 364 - 1 - - - 2287 - regular - 364 - 2284 - 1 - - - 2479 - regular - 363 - 2284 - 1 - - - 2481 - regular - 1618 - 2480 - 1 - - - 2482 - regular - 332 - 2480 - 1 - - - 2483 - regular - 1661 - 2480 - 1 - - - 2485 - regular - 2480 - 2484 - 1 - - - 2730 - regular - 2728 - 2729 - 1 - - - 2731 - regular - 2729 - 2728 - 1 - - - 2732 - regular - 1618 - 2728 - 1 - - - 2733 - regular - 332 - 2728 - 1 - - - 2734 - regular - 1661 - 2728 - 1 - - \ No newline at end of file diff --git a/src/main/resources/petriNets/leukemia.xml b/src/main/resources/petriNets/leukemia.xml deleted file mode 100644 index 8597ba75d02..00000000000 --- a/src/main/resources/petriNets/leukemia.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - examples/leukemia/leukemia - 1.0.0 - LEU - Protokol o začatí a kontrole liečby chronickej myelocytovej leukémie - local_hospital - true - false - - - - - text_0 - Poznámka - area - - - text_1 - Kód lekára - - - text_2 - Meno lekára - - - text_3 - Priezvisko lekára - - - text_4 - Kód PZS - - - text_5 - Názov zdrav. zariadenia - - - text_6 - Adresa - ulica - - - text_7 - Adresa - mesto - - - text_8 - Adresa - PSČ - - - text_9 - IČO - - - text_10 - Tel. kontakt - - - text_11 - Email - V prípade vyplnenia emailu bude poskytovateľ notifikovaný o stavoch spracovania žiadosti - - - enumeration_0 - Liečba - Začatie liečby - Pokračovanie liečby - Ukončenie liečby - - - - 1 - 190 - 118 - - 3 - - text_0 - - editable - - - 0 - 0 - 2 - 3 - - outline - - - - text_1 - - editable - required - - - 0 - 3 - 1 - 1 - - outline - - - - text_2 - - editable - required - - - 1 - 3 - 1 - 1 - - outline - - - - text_3 - - editable - required - - - 2 - 3 - 1 - 1 - - outline - - - - text_4 - - editable - required - - - 0 - 4 - 1 - 1 - - outline - - - - text_5 - - editable - required - - - 1 - 4 - 1 - 2 - - outline - - - - text_6 - - editable - required - - - 0 - 5 - 1 - 3 - - outline - - - - text_7 - - editable - required - - - 0 - 6 - 1 - 2 - - outline - - - - text_8 - - editable - required - - - 2 - 6 - 1 - 1 - - outline - - - - text_9 - - editable - - - 0 - 7 - 1 - 1 - - outline - - - - text_10 - - editable - required - - - 1 - 7 - 1 - 1 - - outline - - - - text_11 - - editable - - - 2 - 7 - 1 - 1 - - outline - - - - enumeration_0 - - editable - required - - - 0 - 2 - 1 - 3 - - outline - - - - - - \ No newline at end of file diff --git a/src/main/resources/petriNets/leukemia_en.xml b/src/main/resources/petriNets/leukemia_en.xml deleted file mode 100644 index 0bee06055c3..00000000000 --- a/src/main/resources/petriNets/leukemia_en.xml +++ /dev/null @@ -1,273 +0,0 @@ - - - leukemia/leu - 1.0.0 - LEU - Protocol on treatment of chronic myelocytic leukemia - local_hospital - true - false - - - - - text_0 - Notes - area - - - text_1 - Doctor code - - - text_2 - Doctor name - - - text_3 - Doctor surname - - - text_4 - Health care provider code - - - text_5 - Provider name - - - text_6 - Adress - street - - - text_7 - Adress - city - - - text_8 - Adress - ZIP code - - - text_9 - Company ID - - - text_10 - Tel. number - - - text_11 - Email - If the email is filled in, the provider will be notified of the processing status of the application - - - - enumeration_0 - Treatment - New treatment - Continuing treatment - End of treatment - - - - 1 - 190 - 118 - - 3 - - text_0 - - editable - - - 0 - 0 - 2 - 3 - - outline - - - - text_1 - - editable - required - - - 0 - 3 - 1 - 1 - - outline - - - - text_2 - - editable - required - - - 1 - 3 - 1 - 1 - - outline - - - - text_3 - - editable - required - - - 2 - 3 - 1 - 1 - - outline - - - - text_4 - - editable - required - - - 0 - 4 - 1 - 1 - - outline - - - - text_5 - - editable - required - - - 1 - 4 - 1 - 2 - - outline - - - - text_6 - - editable - required - - - 0 - 5 - 1 - 3 - - outline - - - - text_7 - - editable - required - - - 0 - 6 - 1 - 2 - - outline - - - - text_8 - - editable - required - - - 2 - 6 - 1 - 1 - - outline - - - - text_9 - - editable - - - 0 - 7 - 1 - 1 - - outline - - - - text_10 - - editable - required - - - 1 - 7 - 1 - 1 - - outline - - - - text_11 - - editable - - - 2 - 7 - 1 - 1 - - outline - - - - enumeration_0 - - editable - required - - - 0 - 2 - 1 - 3 - - outline - - - - - - diff --git a/src/main/resources/petriNets/petriflow_schema.xsd b/src/main/resources/petriNets/petriflow_schema.xsd index 28e88a26d6f..830dfa3f813 100644 --- a/src/main/resources/petriNets/petriflow_schema.xsd +++ b/src/main/resources/petriNets/petriflow_schema.xsd @@ -1,8 +1,854 @@ - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/petriNets/petriflow_schema_layout.xsd b/src/main/resources/petriNets/petriflow_schema_layout.xsd new file mode 100644 index 00000000000..d48dad2d97f --- /dev/null +++ b/src/main/resources/petriNets/petriflow_schema_layout.xsd @@ -0,0 +1,1000 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/petriNets/posudky.xml b/src/main/resources/petriNets/posudky.xml deleted file mode 100644 index b91919f3a4d..00000000000 --- a/src/main/resources/petriNets/posudky.xml +++ /dev/null @@ -1,351 +0,0 @@ - - - management/posudky - Posudky - PSD - Posudok - - - - role1 - role1 - - - - datum - Datum - - - student_meno - Meno študenta - - - student_priezvisko - Priezvisko študenta - - - student_titul - Titul študenta - - - praca_nazov - Názov práce - - - praca_program - Študijný program - Aplikovaná informatika - Mechatronika - Aplikovaná informatika - - - praca_veduci - Meno vedúceho - - - praca_oponent - Meno oponenta - - - - 2 - 300 - 260 - - auto - - student - Študent - - datum - - required - editable - - - - student_meno - - required - editable - - - - student_priezvisko - - required - editable - - - - student_titul - - editable - - - - - praca - Práca - - praca_nazov - - required - editable - - - - praca_program - - required - editable - - - - praca_veduci - - required - editable - - veduci: f.praca_veduci; - - change veduci value { - useCase.author.fullName - } - - - - - praca_oponent - - required - editable - - - - - - 7 - 580 - 140 - - - - 8 - 580 - 220 - - - - 9 - 580 - 300 - - - - 10 - 580 - 380 - - - - 19 - 860 - 260 - - - - - 1 - 180 - 260 - - 1 - false - - - 3 - 460 - 140 - - 0 - false - - - 4 - 460 - 220 - - 0 - false - - - 5 - 460 - 300 - - 0 - false - - - 6 - 460 - 380 - - 0 - false - - - 15 - 700 - 140 - - 0 - false - - - 16 - 700 - 220 - - 0 - false - - - 17 - 700 - 300 - - 0 - false - - - 18 - 700 - 380 - - 0 - false - - - - 11 - read - 3 - 7 - 1 - - - 12 - read - 4 - 8 - 1 - - - 13 - read - 5 - 9 - 1 - - - 14 - read - 6 - 10 - 1 - - - 22 - regular - 1 - 2 - 1 - - - 23 - regular - 2 - 3 - 1 - - - 24 - regular - 2 - 4 - 1 - - - 25 - regular - 2 - 5 - 1 - - - 26 - regular - 2 - 6 - 1 - - - 27 - regular - 10 - 18 - 1 - - - 28 - regular - 9 - 17 - 1 - - - 29 - regular - 8 - 16 - 1 - - - 30 - regular - 7 - 15 - 1 - - - 44 - read - 15 - 19 - 1 - - - 45 - read - 17 - 19 - 1 - - - 46 - read - 16 - 19 - 1 - - - 47 - read - 18 - 19 - 1 - - \ No newline at end of file diff --git a/src/main/resources/petriNets/test_model_immediate_data.xml b/src/main/resources/petriNets/test_model_immediate_data.xml deleted file mode 100644 index 7ef55217802..00000000000 --- a/src/main/resources/petriNets/test_model_immediate_data.xml +++ /dev/null @@ -1,329 +0,0 @@ - - true - Nový prípad - - - tester - Tester - - - - boolean_field - Boolean - true - 3 - - - text_field - Text - email - - - text_area_field - Text Area - area - The 39th International Conference on Applications and Theory of Petri Nets and Concurrency will be held - June 24-29, 2018 Austria Trend Hotel Bratislava, Vysoka 2A, 811 06 Bratislava, Slovakia. The conference will - be co-located with the 18th International Conference on Application of Concurrency to System Design (ACSD - 2018). - - 10 - - - number_field - Number - 38.579 - - - EUR - 3 - sk_SK - - - 5 - - - number_field2 - Number2 - 38 - 2 - - - date_field - Date - 3 - - - enumeration_field - Enumeration - WTF - Alfa - Bravo - Charlie - Delta - Echo - Foxtrot - Golf - Hotel - India - Juliett - Kilo - Lima - Mike - November - Oscar - Papa - Quebec - Romeo - Sierra - Tango - Uniform - Victor - Whiskey - X-ray - Yankee - Zulu - - - - - - multichoice_field - Multichoice - Value 1 - Value 2 - Value 3 - Value 3 - - - user_field - User - tester - - - file_field - File - - - datetime_field - Date Time - - - - New case - - - - 2 - 220 - 180 - - edit - 1 - auto - - 1 - Simple fields - start - - boolean_field - - editable - - - - text_field - - editable - - - - text_area_field - - editable - - - - number_field - - editable - - - - number_field2 - - editable - - - - - 2 - Select fields - start - - enumeration_field - - editable - - - - multichoice_field - - editable - - - - - 3 - Complex fields - start - - user_field - - editable - - - - file_field - - editable - - - - - 4 - Date fields - start - - datetime_field - - editable - - - - date_field - - editable - - - - - - 3 - 340 - 300 - - done - 2 - - 1 - Simple fields - start - - boolean_field - - editable - - - - text_field - - editable - - - - number_field - - editable - - - - date_field - - editable - - - - - 2 - Select fields - start - - enumeration_field - - editable - - - - multichoice_field - - editable - - - - - 3 - Complex fields - start - - user_field - - editable - - - - file_field - - editable - - - - - - - 1 - 220 - 300 - - 1 - false - - - 7 - 500 - 300 - - 0 - false - - - - 4 - regular - 1 - 2 - 1 - - - 5 - regular - 1 - 3 - 1 - - - 6 - regular - 2 - 1 - 1 - - - 8 - regular - 3 - 7 - 1 - - \ No newline at end of file diff --git a/src/main/resources/petriNets/wizard.xml b/src/main/resources/petriNets/wizard.xml deleted file mode 100644 index c4acf2f9dd8..00000000000 --- a/src/main/resources/petriNets/wizard.xml +++ /dev/null @@ -1,246 +0,0 @@ - - - - text - text - - - - 5 - 260 - 340 - - - step1_finish - Ďalej - - - - 6 - 500 - 340 - - - step2_finish - Ďalej - - - step2_cancel - Späť - - - textf: f.text; - change textf about { - "changed" - } - - - task: t.7; - executeTask("8",[:] as Map) - - - - - - 7 - 740 - 340 - - - step3_finish - Ďalej - - - step3_cancel - Späť - - - task: t.7; - executeTask("9",[:] as Map) - - - - - - 23 - 980 - 260 - - - step2_cancel - Späť - - - - 8 - 260 - 180 - - - - 9 - 500 - 180 - - - - 24 - 740 - 180 - - - - 26 - 1220 - 260 - - - - - 1 - 140 - 260 - - 1 - false - - - 2 - 380 - 260 - - 0 - false - - - 3 - 620 - 260 - - 0 - false - - - 4 - 860 - 260 - - 0 - false - - - 25 - 1100 - 260 - - 0 - false - - - - 11 - regular - 1 - 5 - 1 - - - 12 - regular - 5 - 2 - 1 - - - 13 - regular - 2 - 6 - 1 - - - 14 - regular - 6 - 3 - 1 - - - 15 - regular - 3 - 7 - 1 - - - 16 - regular - 7 - 4 - 1 - - - 19 - regular - 3 - 9 - 1 - - - 20 - regular - 9 - 2 - 1 - - - 21 - regular - 2 - 8 - 1 - - - 22 - regular - 8 - 1 - 1 - - - 27 - read - 25 - 26 - 1 - - - 28 - regular - 4 - 23 - 1 - - - 29 - regular - 23 - 25 - 1 - - - 30 - regular - 4 - 24 - 1 - - - 31 - regular - 24 - 3 - 1 - - \ No newline at end of file diff --git a/src/test/groovy/com/netgrif/application/engine/Async.groovy b/src/test/groovy/com/netgrif/application/engine/Async.groovy index fa7758e6bd7..b5705726afa 100644 --- a/src/test/groovy/com/netgrif/application/engine/Async.groovy +++ b/src/test/groovy/com/netgrif/application/engine/Async.groovy @@ -3,6 +3,7 @@ package com.netgrif.application.engine import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.workflow.domain.State import com.netgrif.application.engine.workflow.domain.Task +import com.netgrif.application.engine.workflow.domain.params.TaskParams import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import groovy.transform.CompileStatic @@ -44,8 +45,8 @@ class Async { def t1Id = $case.getTaskStringId("t1") - taskService.assignTask(t1Id) - taskService.finishTask(t1Id) + taskService.assignTask(new TaskParams(t1Id)) + taskService.finishTask(new TaskParams(t1Id)) $case = workflowService.findOne($case.stringId) List tasks = taskService.findAllByCase($case.stringId) diff --git a/src/test/groovy/com/netgrif/application/engine/EngineTest.groovy b/src/test/groovy/com/netgrif/application/engine/EngineTest.groovy new file mode 100644 index 00000000000..32603d6c3a5 --- /dev/null +++ b/src/test/groovy/com/netgrif/application/engine/EngineTest.groovy @@ -0,0 +1,65 @@ +package com.netgrif.application.engine + +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authorization.service.interfaces.IUserService +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService +import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService +import com.netgrif.application.engine.petrinet.service.interfaces.IUriService +import com.netgrif.application.engine.startup.ImportHelper +import com.netgrif.application.engine.startup.SuperCreator +import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository +import com.netgrif.application.engine.workflow.service.interfaces.IDataService +import com.netgrif.application.engine.workflow.service.interfaces.ITaskService +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService +import org.junit.jupiter.api.BeforeEach +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.web.context.WebApplicationContext + +@SpringBootTest +abstract class EngineTest { + @Autowired + public ImportHelper importHelper + @Autowired + public TestHelper testHelper + @Autowired + public SuperCreator superCreator + @Autowired + public WebApplicationContext wac + + // SERVICE + @Autowired + public ITaskService taskService + @Autowired + public IRoleService roleService + @Autowired + public IIdentityService identityService + @Autowired + public ISessionManagerService sessionManagerService + @Autowired + public IUserService userService + @Autowired + public IWorkflowService workflowService + @Autowired + public IPetriNetService petriNetService + @Autowired + public IDataService dataService + @Autowired + public IUriService uriService + @Autowired + public IElasticCaseService elasticCaseService + + // REPOSITORY + @Autowired + public PetriNetRepository processRepository + @Autowired + public CaseRepository caseRepository + + @BeforeEach + void before() { + testHelper.truncateDbs() + } +} diff --git a/src/test/groovy/com/netgrif/application/engine/TestHelper.groovy b/src/test/groovy/com/netgrif/application/engine/TestHelper.groovy index db7992527bc..fc1fd0a4354 100644 --- a/src/test/groovy/com/netgrif/application/engine/TestHelper.groovy +++ b/src/test/groovy/com/netgrif/application/engine/TestHelper.groovy @@ -1,16 +1,24 @@ package com.netgrif.application.engine -import com.netgrif.application.engine.auth.domain.repositories.UserRepository -import com.netgrif.application.engine.elastic.domain.ElasticCaseRepository -import com.netgrif.application.engine.elastic.domain.ElasticTaskRepository -import com.netgrif.application.engine.petrinet.domain.repository.UriNodeRepository -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository -import com.netgrif.application.engine.petrinet.service.ProcessRoleService +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.LoggedIdentity +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authorization.domain.repositories.RoleAssignmentRepository +import com.netgrif.application.engine.authorization.domain.repositories.RoleRepository +import com.netgrif.application.engine.authorization.service.RoleService +import com.netgrif.application.engine.authorization.service.interfaces.IGroupService +import com.netgrif.application.engine.authorization.service.interfaces.IUserService +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticCaseRepository +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticTaskRepository +import com.netgrif.application.engine.petrinet.domain.repositories.UriNodeRepository import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.* import com.netgrif.application.engine.workflow.service.interfaces.IFieldActionsCacheService import org.springframework.beans.factory.annotation.Autowired +import org.springframework.context.annotation.Lazy import org.springframework.data.mongodb.core.MongoTemplate +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken +import org.springframework.security.core.context.SecurityContextHolder import org.springframework.stereotype.Component @Component @@ -21,17 +29,21 @@ class TestHelper { @Autowired private MongoTemplate template @Autowired - private UserRepository userRepository + private RoleRepository roleRepository @Autowired - private ProcessRoleRepository roleRepository + private RoleAssignmentRepository roleAssignmentRepository @Autowired - private ProcessRoleService roleService + private RoleService roleService @Autowired - private SystemUserRunner systemUserRunner + private SystemUserRunner systemIdentityRunner + @Lazy @Autowired - private DefaultRoleRunner defaultRoleRunner + private SystemProcessRunner systemProcessRunner @Autowired - private AnonymousRoleRunner anonymousRoleRunner + private ApplicationRoleRunner applicationRoleRunner + @Lazy + @Autowired + private AnonymousIdentityRunner anonymousIdentityRunner @Autowired private ElasticTaskRepository elasticTaskRepository @Autowired @@ -39,41 +51,66 @@ class TestHelper { @Autowired private UriNodeRepository uriNodeRepository @Autowired - private GroupRunner groupRunner - @Autowired private IFieldActionsCacheService actionsCacheService @Autowired private FilterRunner filterRunner @Autowired private FinisherRunner finisherRunner @Autowired - private ImpersonationRunner impersonationRunner - @Autowired private UriRunner uriRunner @Autowired private IPetriNetService petriNetService + @Autowired + private ValidationRunner validationRunner + @Autowired + private DefaultGroupRunner defaultGroupRunner + @Autowired + private IUserService userService + @Autowired + private IGroupService groupService + @Autowired + private IIdentityService identityService; void truncateDbs() { template.db.drop() elasticTaskRepository.deleteAll() elasticCaseRepository.deleteAll() uriNodeRepository.deleteAll() - userRepository.deleteAll() + roleAssignmentRepository.deleteAll() roleRepository.deleteAll() roleService.clearCache() actionsCacheService.clearActionCache() actionsCacheService.clearFunctionCache() actionsCacheService.clearNamespaceFunctionCache() petriNetService.evictAllCaches() + userService.clearForbiddenKeywords() + groupService.clearForbiddenKeywords() + identityService.clearForbiddenKeywords() - defaultRoleRunner.run() - anonymousRoleRunner.run() - systemUserRunner.run() uriRunner.run() - groupRunner.run() + systemProcessRunner.run() + applicationRoleRunner.run() + defaultGroupRunner.run() + systemIdentityRunner.run() + anonymousIdentityRunner.run() filterRunner.run() - impersonationRunner.run() superCreator.run() + validationRunner.run() finisherRunner.run() } + + static void login(Identity identity) { + LoggedIdentity loggedTest = identity.toSession() + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loggedTest, + loggedTest.getPassword(), loggedTest.getAuthorities()) + SecurityContextHolder.getContext().setAuthentication(token) + } + + static void logout() { + SecurityContextHolder.getContext().setAuthentication(null) + } + + static InputStream stream(String resource) { + return TestHelper.getClassLoader().getResourceAsStream(resource) + } } \ No newline at end of file diff --git a/src/test/groovy/com/netgrif/application/engine/action/ActionDelegateTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/ActionDelegateTest.groovy index 4183e5134a9..aeb42cf3aab 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/ActionDelegateTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/ActionDelegateTest.groovy @@ -3,15 +3,14 @@ package com.netgrif.application.engine.action import com.icegreen.greenmail.util.GreenMail import com.icegreen.greenmail.util.ServerSetup import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.IUser -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.auth.web.requestbodies.NewUserRequest + + +import com.netgrif.application.engine.authentication.web.requestbodies.NewIdentityRequest import com.netgrif.application.engine.configuration.PublicViewProperties import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionDelegate import com.netgrif.application.engine.workflow.service.interfaces.IFilterImportExportService import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired @@ -37,9 +36,6 @@ class ActionDelegateTest { @Autowired private IFilterImportExportService importExportService - @Autowired - private IUserService userService - @Autowired private PublicViewProperties publicViewProperties @@ -53,7 +49,7 @@ class ActionDelegateTest { GreenMail smtpServer = new GreenMail(new ServerSetup(2525, null, "smtp")) smtpServer.start() - MessageResource messageResource = actionDelegate.inviteUser("test@netgrif.com") + MessageResource messageResource = actionDelegate.inviteIdentity("test@netgrif.com") assert messageResource.getContent().success MimeMessage[] messages = smtpServer.getReceivedMessages() @@ -63,19 +59,19 @@ class ActionDelegateTest { @Test void deleteUser(){ - GreenMail smtpServer = new GreenMail(new ServerSetup(2525, null, "smtp")) - smtpServer.start() - String mail = "test@netgrif.com"; - MessageResource messageResource = actionDelegate.inviteUser(mail) - assert messageResource.getContent().success - IUser user = userService.findByEmail(mail, false) - assert user != null - MimeMessage[] messages = smtpServer.getReceivedMessages() - assert messages - actionDelegate.deleteUser(mail) - IUser user2 = userService.findByEmail(mail, false) - assert user2 == null - smtpServer.stop() +// GreenMail smtpServer = new GreenMail(new ServerSetup(2525, null, "smtp")) +// smtpServer.start() +// String mail = "test@netgrif.com"; +// MessageResource messageResource = actionDelegate.inviteIdentity(mail) +// assert messageResource.getContent().success +// IUser user = userService.findByEmail(mail) +// assert user != null +// MimeMessage[] messages = smtpServer.getReceivedMessages() +// assert messages +// actionDelegate.deleteUser(mail) +// IUser user2 = userService.findByEmail(mail) +// assert user2 == null +// smtpServer.stop() } @@ -84,12 +80,12 @@ class ActionDelegateTest { GreenMail smtpServer = new GreenMail(new ServerSetup(2525, null, "smtp")) smtpServer.start() - NewUserRequest newUserRequest = new NewUserRequest() + NewIdentityRequest newUserRequest = new NewIdentityRequest() newUserRequest.setEmail("test@netgrif.com") newUserRequest.groups = new HashSet<>() - newUserRequest.processRoles = new HashSet<>() + newUserRequest.roles = new HashSet<>() - MessageResource messageResource = actionDelegate.inviteUser(newUserRequest) + MessageResource messageResource = actionDelegate.inviteIdentity(newUserRequest) assert messageResource.getContent().success MimeMessage[] messages = smtpServer.getReceivedMessages() diff --git a/src/test/groovy/com/netgrif/application/engine/action/ActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/ActionTest.groovy index 29991f0adc5..2d9c787cfb0 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/ActionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/ActionTest.groovy @@ -5,13 +5,17 @@ import com.netgrif.application.engine.importer.model.CaseEventType import com.netgrif.application.engine.importer.model.DataEventType import com.netgrif.application.engine.importer.model.EventType import com.netgrif.application.engine.importer.model.ProcessEventType +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionRunner +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.SetDataType import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.Task import groovy.transform.CompileStatic +import groovy.util.logging.Slf4j import org.bson.types.ObjectId +import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired @@ -19,6 +23,7 @@ import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension +@Slf4j @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @SpringBootTest @@ -34,21 +39,29 @@ class ActionTest { @Autowired private ImportHelper importHelper + @BeforeEach + void beforeAll() { + testHelper.truncateDbs() + } + @Test void testActionImports() { + Process process = new Process() Case dummy = new Case() + dummy.process = process Task task = Task.with().id(new ObjectId()).transitionId("0").build() - Action testAction = new Action(''' + Action testAction = new Action() + testAction.definition = ''' println LocalDate.now() println LocalDate.MAX println new ObjectId().toString() - ''', "set") + ''' + testAction.setDataType = SetDataType.VALUE runner.run(testAction, dummy, Optional.of(task), null, [:]) } @Test void testImportActionWithId() { - testHelper.truncateDbs() def netOptional = importHelper.createNet("NAE-1616_duplicate_action_id.xml") assert netOptional.isPresent() def net = netOptional.get() @@ -64,26 +77,27 @@ class ActionTest { assert net.caseEvents.get(CaseEventType.DELETE).preActions.first().definition.contains("case_delete_pre") assert net.caseEvents.get(CaseEventType.DELETE).postActions.size() == 1 assert net.caseEvents.get(CaseEventType.DELETE).postActions.first().definition.contains("case_delete_post") - def role = net.roles.values().first() - assert role.events.get(EventType.ASSIGN).preActions.size() == 1 - assert role.events.get(EventType.ASSIGN).preActions.first().definition.contains("role_assign_pre") - assert role.events.get(EventType.ASSIGN).postActions.size() == 1 - assert role.events.get(EventType.ASSIGN).postActions.first().definition.contains("role_assign_post") - assert role.events.get(EventType.CANCEL).preActions.size() == 1 - assert role.events.get(EventType.CANCEL).preActions.first().definition.contains("role_cancel_pre") - assert role.events.get(EventType.CANCEL).postActions.size() == 1 - assert role.events.get(EventType.CANCEL).postActions.first().definition.contains("role_cancel_post") + // TODO: release/8.0.0 fix +// def role = net.roles.values().find { it.importId == "newRole_1" } +// assert role.events.get(EventType.ASSIGN).preActions.size() == 1 +// assert role.events.get(EventType.ASSIGN).preActions.first().definition.contains("role_assign_pre") +// assert role.events.get(EventType.ASSIGN).postActions.size() == 1 +// assert role.events.get(EventType.ASSIGN).postActions.first().definition.contains("role_assign_post") +// assert role.events.get(EventType.CANCEL).preActions.size() == 1 +// assert role.events.get(EventType.CANCEL).preActions.first().definition.contains("role_cancel_pre") +// assert role.events.get(EventType.CANCEL).postActions.size() == 1 +// assert role.events.get(EventType.CANCEL).postActions.first().definition.contains("role_cancel_post") def data = net.dataSet.values().first() assert data.events.get(DataEventType.GET).preActions.size() == 2 - assert data.events.get(DataEventType.GET).preActions.find {it.importId == "NAE_1616-12"}.definition.contains("data_trigger_get") - assert data.events.get(DataEventType.GET).preActions.find {it.importId == "NAE_1616-15"}.definition.contains("data_get_pre") + assert data.events.get(DataEventType.GET).preActions.find { it.importId == "NAE_1616-12" }.definition.contains("data_trigger_get") + assert data.events.get(DataEventType.GET).preActions.find { it.importId == "NAE_1616-15" }.definition.contains("data_get_pre") assert data.events.get(DataEventType.GET).postActions.size() == 1 assert data.events.get(DataEventType.GET).postActions.first().definition.contains("data_get_post") assert data.events.get(DataEventType.SET).preActions.size() == 1 assert data.events.get(DataEventType.SET).preActions.first().definition.contains("data_set_pre") assert data.events.get(DataEventType.SET).postActions.size() == 2 - assert data.events.get(DataEventType.SET).postActions.find {it.importId == "NAE_1616-11"}.definition.contains("data_trigger_set") - assert data.events.get(DataEventType.SET).postActions.find {it.importId == "NAE_1616-14"}.definition.contains("data_set_post") + assert data.events.get(DataEventType.SET).postActions.find { it.importId == "NAE_1616-11" }.definition.contains("data_trigger_set") + assert data.events.get(DataEventType.SET).postActions.find { it.importId == "NAE_1616-14" }.definition.contains("data_set_post") def task = net.getTransitions().values().first() assert task.events.get(EventType.ASSIGN).preActions.size() == 1 assert task.events.get(EventType.ASSIGN).preActions.first().definition.contains("task_assign_pre") @@ -93,35 +107,35 @@ class ActionTest { assert task.events.get(EventType.CANCEL).preActions.first().definition.contains("task_cancel_pre") assert task.events.get(EventType.CANCEL).postActions.size() == 1 assert task.events.get(EventType.CANCEL).postActions.first().definition.contains("task_cancel_post") - assert task.events.get(EventType.DELEGATE).preActions.size() == 1 - assert task.events.get(EventType.DELEGATE).preActions.first().definition.contains("task_delegate_pre") - assert task.events.get(EventType.DELEGATE).postActions.size() == 1 - assert task.events.get(EventType.DELEGATE).postActions.first().definition.contains("task_delegate_post") + assert task.events.get(EventType.REASSIGN).preActions.size() == 1 + assert task.events.get(EventType.REASSIGN).preActions.first().definition.contains("task_delegate_pre") + assert task.events.get(EventType.REASSIGN).postActions.size() == 1 + assert task.events.get(EventType.REASSIGN).postActions.first().definition.contains("task_delegate_post") assert task.events.get(EventType.FINISH).preActions.size() == 1 assert task.events.get(EventType.FINISH).preActions.first().definition.contains("task_finish_pre") assert task.events.get(EventType.FINISH).postActions.size() == 1 assert task.events.get(EventType.FINISH).postActions.first().definition.contains("task_finish_post") def data_text_0 = task.dataSet.get("text_0") assert data_text_0.events.get(DataEventType.GET).preActions.size() == 2 - assert data_text_0.events.get(DataEventType.GET).preActions.find {it.importId == "NAE_1616-17"}.definition.contains("text_0_dataref_trigger_get") - assert data_text_0.events.get(DataEventType.GET).preActions.find {it.importId == "NAE_1616-21"}.definition.contains("text_0_dataref_get_pre") + assert data_text_0.events.get(DataEventType.GET).preActions.find { it.importId == "NAE_1616-17" }.definition.contains("text_0_dataref_trigger_get") + assert data_text_0.events.get(DataEventType.GET).preActions.find { it.importId == "NAE_1616-21" }.definition.contains("text_0_dataref_get_pre") assert data_text_0.events.get(DataEventType.GET).postActions.size() == 1 assert data_text_0.events.get(DataEventType.GET).postActions.first().definition.contains("text_0_dataref_get_post") assert data_text_0.events.get(DataEventType.SET).preActions.size() == 1 assert data_text_0.events.get(DataEventType.SET).preActions.first().definition.contains("text_0_dataref_set_pre") assert data_text_0.events.get(DataEventType.SET).postActions.size() == 2 - assert data_text_0.events.get(DataEventType.SET).postActions.find {it.importId == "NAE_1616-18"}.definition.contains("text_0_dataref_trigger_set") - assert data_text_0.events.get(DataEventType.SET).postActions.find {it.importId == "NAE_1616-20"}.definition.contains("text_0_dataref_set_post") + assert data_text_0.events.get(DataEventType.SET).postActions.find { it.importId == "NAE_1616-18" }.definition.contains("text_0_dataref_trigger_set") + assert data_text_0.events.get(DataEventType.SET).postActions.find { it.importId == "NAE_1616-20" }.definition.contains("text_0_dataref_set_post") def data_text_1 = task.dataSet.get("text_1") assert data_text_1.events.get(DataEventType.GET).preActions.size() == 2 - assert data_text_1.events.get(DataEventType.GET).preActions.find {it.importId == "NAE_1616-31"}.definition.contains("text_1_dataref_trigger_get") - assert data_text_1.events.get(DataEventType.GET).preActions.find {it.importId == "NAE_1616-35"}.definition.contains("text_1_dataref_get_pre") + assert data_text_1.events.get(DataEventType.GET).preActions.find { it.importId == "NAE_1616-31" }.definition.contains("text_1_dataref_trigger_get") + assert data_text_1.events.get(DataEventType.GET).preActions.find { it.importId == "NAE_1616-35" }.definition.contains("text_1_dataref_get_pre") assert data_text_1.events.get(DataEventType.GET).postActions.size() == 1 assert data_text_1.events.get(DataEventType.GET).postActions.first().definition.contains("text_1_dataref_get_post") assert data_text_1.events.get(DataEventType.SET).preActions.size() == 1 assert data_text_1.events.get(DataEventType.SET).preActions.first().definition.contains("text_1_dataref_set_pre") assert data_text_1.events.get(DataEventType.SET).postActions.size() == 2 - assert data_text_1.events.get(DataEventType.SET).postActions.find {it.importId == "NAE_1616-32"}.definition.contains("text_1_dataref_trigger_set") - assert data_text_1.events.get(DataEventType.SET).postActions.find {it.importId == "NAE_1616-34"}.definition.contains("text_1_dataref_set_post") + assert data_text_1.events.get(DataEventType.SET).postActions.find { it.importId == "NAE_1616-32" }.definition.contains("text_1_dataref_trigger_set") + assert data_text_1.events.get(DataEventType.SET).postActions.find { it.importId == "NAE_1616-34" }.definition.contains("text_1_dataref_set_post") } } diff --git a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy deleted file mode 100644 index f67f8f90585..00000000000 --- a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy +++ /dev/null @@ -1,146 +0,0 @@ -package com.netgrif.application.engine.action - -import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.domain.repositories.UserRepository -import com.netgrif.application.engine.importer.service.Importer -import com.netgrif.application.engine.petrinet.domain.PetriNet -import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.startup.SuperCreator -import groovy.json.JsonOutput -import groovy.transform.CompileStatic -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.data.mongodb.core.MongoTemplate -import org.springframework.hateoas.MediaTypes -import org.springframework.http.MediaType -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.security.core.Authentication -import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors -import org.springframework.security.web.authentication.WebAuthenticationDetails -import org.springframework.test.context.ActiveProfiles -import org.springframework.test.context.junit.jupiter.SpringExtension -import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders -import org.springframework.test.web.servlet.result.MockMvcResultMatchers -import org.springframework.test.web.servlet.setup.MockMvcBuilders -import org.springframework.web.context.WebApplicationContext - -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication -import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity - -@ExtendWith(SpringExtension.class) -@ActiveProfiles(["test"]) -@SpringBootTest -@CompileStatic -class AssignActionTest { - - private static final String GROUP_NAME = "Test group" - public static final String USER_EMAIL = "test@mail.sk" - public static final String USER_PASSWORD = "password" - - public static final String ROLE_API = "/api/user/{}/role/assign" - - @Autowired - private Importer importer - - @Autowired - private ImportHelper importHelper - - @Autowired - private WebApplicationContext wac - - @Autowired - private MongoTemplate template - - @Autowired - private UserRepository userRepository - - @Autowired - private ProcessRoleRepository processRoleRepository - - @Autowired - private IPetriNetService petriNetService - - @Autowired - private SuperCreator superCreator - - @Autowired - private TestHelper testHelper - - private MockMvc mvc - private PetriNet mainNet - private PetriNet secondaryNet - private UsernamePasswordAuthenticationToken authentication - - @BeforeEach - void before() { - testHelper.truncateDbs() - - mvc = MockMvcBuilders - .webAppContextSetup(wac) - .apply(springSecurity()) - .build() - - createMainAndSecondaryNet() - - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - - importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), - [auths.get("user"), auths.get("admin")] as Authority[], -// [org] as Group[], - [] as ProcessRole[]) - } - - private void createMainAndSecondaryNet() { - def mainNet = petriNetService.importPetriNet(new FileInputStream("src/test/resources/assignRoleMainNet_test_.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert mainNet.getNet() != null - - def secondaryNet = petriNetService.importPetriNet(new FileInputStream("src/test/resources/assignRoleSecondaryNet_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert secondaryNet.getNet() != null - - this.mainNet = mainNet.getNet() - this.secondaryNet = secondaryNet.getNet() - } - - @Test - void testAssignRoleOnSecondaryNetWhenRoleIsAddedOnPrimaryNet() { - User user = userRepository.findByEmail(USER_EMAIL) - - authentication = new UsernamePasswordAuthenticationToken(USER_EMAIL, USER_PASSWORD) - authentication.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())); - - String roleIdInMainNet = mainNet.getRoles().find { it.value.name.defaultValue == "admin_main" }.key - - def content = JsonOutput.toJson([roleIdInMainNet]) - String userId = user.getStringId() - - def result = mvc.perform(MockMvcRequestBuilders.post(ROLE_API.replace("{}", userId)) - .accept(MediaTypes.HAL_JSON_VALUE) - .content(content) - .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE) - .with(SecurityMockMvcRequestPostProcessors.csrf().asHeader()) - .with(SecurityMockMvcRequestPostProcessors.authentication(authentication))) - .andExpect(MockMvcResultMatchers.status().isOk()) - .andReturn() - - User updatedUser = userRepository.findByEmail(USER_EMAIL) - Set roles = updatedUser.getProcessRoles() - - String adminMainId = processRoleRepository.findAllByName_DefaultValue("admin_main")?.first()?.stringId - String adminSecondaryId = processRoleRepository.findAllByName_DefaultValue("admin_secondary")?.first()?.stringId - - assert roles.find { it.stringId == adminMainId } - assert roles.find { it.stringId == adminSecondaryId } - } -} diff --git a/src/test/groovy/com/netgrif/application/engine/action/AssignRemoveTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/AssignRemoveTest.groovy index b5ed186ce48..2b515e66e5a 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/AssignRemoveTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/AssignRemoveTest.groovy @@ -1,14 +1,14 @@ package com.netgrif.application.engine.action import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService + import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator -import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import groovy.transform.CompileStatic @@ -18,7 +18,6 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.core.Authentication import org.springframework.security.core.context.SecurityContextHolder import org.springframework.test.context.ActiveProfiles @@ -48,35 +47,34 @@ class AssignRemoveTest { @Autowired private CaseRepository caseRepository - @Autowired - private IUserService userService - private Authentication auth @BeforeEach void before() { testHelper.truncateDbs() - def user = userService.system +// def user = userService.system - auth = new UsernamePasswordAuthenticationToken(user.transformToLoggedUser(), user) +// auth = new UsernamePasswordAuthenticationToken(user.transformToLoggedUser(), user) SecurityContextHolder.getContext().setAuthentication(auth) } @Test @Disabled("Create functions or update test") void testAssignAndRemoveRole() throws MissingPetriNetMetaDataException, IOException { - ImportPetriNetEventOutcome netOptional = petriNetService.importPetriNet(new FileInputStream("src/test/resources/petriNets/role_assign_remove_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - - assert netOptional.getNet() != null - def net = netOptional.getNet() - def roleCount = userService.system.processRoles.size() - - // create - Case caze = workflowService.createCase(net.stringId, 'TEST', '', userService.getLoggedOrSystem().transformToLoggedUser()).getCase() - assert userService.system.processRoles.size() == roleCount + 4 - - // delete - workflowService.deleteCase(caze.stringId) - assert userService.system.processRoles.size() == roleCount + ImportPetriNetEventOutcome netOptional = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/petriNets/role_assign_remove_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + + assert netOptional.getProcess() != null + def net = netOptional.getProcess() + // todo: release/8.0.0 +// def roleCount = userService.system.roles.size() +// +// // create +// Case caze = workflowService.createCase(net.stringId, 'TEST', '', userService.getLoggedOrSystem().transformToLoggedUser()).getCase() +// assert userService.system.roles.size() == roleCount + 4 +// +// // delete +// workflowService.deleteCase(caze.stringId) +// assert userService.system.roles.size() == roleCount } } diff --git a/src/test/groovy/com/netgrif/application/engine/action/ConcurrencyTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/ConcurrencyTest.groovy index 7ffc406467b..4d517bce7ea 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/ConcurrencyTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/ConcurrencyTest.groovy @@ -1,6 +1,6 @@ package com.netgrif.application.engine.action - +import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator @@ -34,8 +34,12 @@ class ConcurrencyTest { @Autowired private SuperCreator superCreator + @Autowired + private TestHelper testHelper + @Test void test() { + TestHelper.login(superCreator.getSuperIdentity()) def mainNet = importHelper.createNet("action_delegate_concurrency_test.xml") assert mainNet.get() != null @@ -48,6 +52,7 @@ class ConcurrencyTest { cases.each { it -> String caseId = it.stringId threads << new Thread({ + TestHelper.login(superCreator.getSuperIdentity()) log.info("Running case $caseId") importHelper.assignTaskToSuper("task", caseId) }) diff --git a/src/test/groovy/com/netgrif/application/engine/action/FilterApiTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/FilterApiTest.groovy index 4e9a86aaf92..20649e30f97 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/FilterApiTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/FilterApiTest.groovy @@ -1,17 +1,15 @@ package com.netgrif.application.engine.action import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService import com.netgrif.application.engine.petrinet.domain.UriContentType import com.netgrif.application.engine.petrinet.domain.dataset.* -import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionDelegate import com.netgrif.application.engine.petrinet.service.interfaces.IUriService import com.netgrif.application.engine.startup.FilterRunner import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.QCase +import com.netgrif.application.engine.workflow.domain.params.SetDataParams import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import com.netgrif.application.engine.workflow.web.responsebodies.DataSet @@ -42,9 +40,6 @@ class FilterApiTest { @Autowired private FilterRunner filterRunner - @Autowired - private IUserService userService - @Autowired private IWorkflowService workflowService @@ -54,9 +49,6 @@ class FilterApiTest { @Autowired private IUriService uriService - @Autowired - private INextGroupService nextGroupService - @Autowired private SuperCreator superCreator @@ -73,21 +65,15 @@ class FilterApiTest { Case item = getMenuItem(caze) Case filter = getFilter(caze) - Case defGroup = nextGroupService.findDefaultGroup() - - assert item.uriNodeId == uriService.findByUri("netgrif/test").id + assert item.uriNodeId == uriService.findByUri("netgrif/test").id.toString() assert item.dataSet.get("icon_name").rawValue == "device_hub" assert item.dataSet.get("entry_name").rawValue.toString() == "FILTER" assert item.dataSet.get("menu_item_identifier").rawValue.toString() == "new_menu_item" - assert item.dataSet.get("parentId").rawValue.toString() == defGroup.stringId assert ((FilterField) filter.dataSet.get("filter")).filterMetadata["filterType"] == "Case" assert ((FilterField) filter.dataSet.get("filter")).rawValue == "processIdentifier:filter OR processIdentifier:preference_filter_item" assert ((FilterField) filter.dataSet.get("filter")).allowedNets == ["filter", "preference_filter_item"] assert filter.dataSet.get("filter_type").rawValue == "Case" - - List taskIds = (defGroup.dataSet.get("filter_tasks").rawValue ?: []) as List - assert taskIds.contains(item.getTaskStringId("view")) } @Test @@ -104,7 +90,7 @@ class FilterApiTest { "icon" : new TextField(rawValue: ""), "create_filter_and_menu": new ButtonField(rawValue: 0) ] as Map>) - dataService.setData(caze.getTaskStringId("t1"), dataSet, superCreator.getLoggedSuper()) + dataService.setData(new SetDataParams(caze.getTaskStringId("t1"), dataSet, superCreator.getLoggedSuper().getActiveActorId())) caze = workflowService.findOne(caze.stringId) Case item = getMenuItem(caze) Case filter = getFilter(caze) @@ -128,11 +114,8 @@ class FilterApiTest { DataSet dataSet = new DataSet([ "delete_filter_and_menu": new ButtonField(rawValue: 0) ] as Map>) - dataService.setData(caze.getTaskStringId("t1"), dataSet, superCreator.getLoggedSuper()) + dataService.setData(new SetDataParams(caze.getTaskStringId("t1"), dataSet, superCreator.getLoggedSuper().getActiveActorId())) workflowService.findOne(caze.stringId) - Case defGroup = nextGroupService.findDefaultGroup() - List taskIds = (defGroup.dataSet.get(ActionDelegate.ORG_GROUP_FIELD_FILTER_TASKS).value.value ?: []) as List - assert !taskIds Thread.sleep(2000) @@ -150,7 +133,7 @@ class FilterApiTest { DataSet dataSet = new DataSet([ "find_filter": new ButtonField(rawValue: 0) ] as Map>) - dataService.setData(caze.getTaskStringId("t1"), dataSet, superCreator.getLoggedSuper()) + dataService.setData(new SetDataParams(caze.getTaskStringId("t1"), dataSet, superCreator.getLoggedSuper().getActiveActorId())) caze = workflowService.findOne(caze.stringId) assert caze.dataSet.get("found_filter").rawValue == filter.stringId } @@ -167,7 +150,7 @@ class FilterApiTest { "icon" : new TextField(rawValue: "device_hub"), "create_filter_and_menu": new ButtonField(rawValue: 0) ] as Map>) - dataService.setData(caze.getTaskStringId("t1"), dataSet, superCreator.getLoggedSuper()) + dataService.setData(new SetDataParams(caze.getTaskStringId("t1"), dataSet, superCreator.getLoggedSuper().getActiveActorId())) caze = workflowService.findOne(caze.stringId) return caze } diff --git a/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy index 3be69d0475e..0a9aeba5fbe 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy @@ -1,30 +1,24 @@ package com.netgrif.application.engine.action +import com.netgrif.application.engine.EngineTest import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService import com.netgrif.application.engine.petrinet.domain.I18nString import com.netgrif.application.engine.petrinet.domain.UriContentType import com.netgrif.application.engine.petrinet.domain.UriNode import com.netgrif.application.engine.petrinet.domain.dataset.ButtonField import com.netgrif.application.engine.petrinet.domain.dataset.TextField -import com.netgrif.application.engine.petrinet.service.interfaces.IUriService import com.netgrif.application.engine.startup.FilterRunner -import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.QCase import com.netgrif.application.engine.workflow.domain.menu.MenuItemConstants -import com.netgrif.application.engine.workflow.service.interfaces.IDataService -import com.netgrif.application.engine.workflow.service.interfaces.ITaskService -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService +import com.netgrif.application.engine.workflow.domain.params.DeleteCaseParams +import com.netgrif.application.engine.workflow.domain.params.SetDataParams +import com.netgrif.application.engine.workflow.domain.params.TaskParams import com.netgrif.application.engine.workflow.web.responsebodies.DataSet import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.context.i18n.LocaleContextHolder import org.springframework.data.domain.PageRequest @@ -37,45 +31,13 @@ import static org.junit.jupiter.api.Assertions.assertThrows @SpringBootTest @ActiveProfiles(["test"]) @ExtendWith(SpringExtension.class) -class MenuItemApiTest { - - @Autowired - private TestHelper testHelper - - @Autowired - private ImportHelper helper - - @Autowired - private FilterRunner filterRunner - - @Autowired - private IUserService userService - - @Autowired - private IWorkflowService workflowService - - @Autowired - private IDataService dataService - - @Autowired - private IUriService uriService - - @Autowired - private INextGroupService nextGroupService - - @Autowired - private IElasticCaseService elasticCaseService - - @Autowired - private ITaskService taskService - - @Autowired - private SuperCreator superCreator +class MenuItemApiTest extends EngineTest { @BeforeEach void before() { - testHelper.truncateDbs() - helper.createNet("filter_api_test.xml") + super.before() + TestHelper.login(superCreator.getSuperIdentity()) + importHelper.createNet("filter_api_test.xml") } @Test @@ -87,19 +49,19 @@ class MenuItemApiTest { Thread.sleep(4000) UriNode leafNode = uriService.findByUri("/netgrif/test/new_menu_item") assert item.uriNodeId == uriService.findByUri("/netgrif/test").stringId - assert item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_MENU_ICON.attributeId].value == "device_hub" - assert item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_MENU_NAME.attributeId].value == new I18nString("FILTER") - assert item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_IDENTIFIER.attributeId].value.toString() == "new_menu_item" - assert (item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_FILTER_CASE.attributeId].value as List)[0] == filter.stringId - assert item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_ALLOWED_ROLES.attributeId].options.containsKey("role_1:filter_api_test") - assert item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_BANNED_ROLES.attributeId].options.containsKey("role_2:filter_api_test") - assert item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CASE_DEFAULT_HEADERS.attributeId].value == "meta-title,meta-title" - assert item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_TASK_DEFAULT_HEADERS.attributeId].value == "meta-title,meta-title" - - assert filter.dataSet["filter"].filterMetadata["filterType"] == "Case" - assert filter.dataSet["filter"].allowedNets == ["filter", "preference_item"] - assert filter.dataSet["filter"].value == "processIdentifier:filter OR processIdentifier:preference_item" - assert filter.dataSet["filter_type"].value == "Case" + assert item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_MENU_ICON.attributeId).rawValue == "device_hub" + assert item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_MENU_NAME.attributeId).rawValue == new I18nString("FILTER") + assert item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_IDENTIFIER.attributeId).rawValue.toString() == "new_menu_item" + assert (item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_FILTER_CASE.attributeId).rawValue as List)[0] == filter.stringId + assert item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_ALLOWED_ROLES.attributeId).options.containsKey("role_1") + assert item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_BANNED_ROLES.attributeId).options.containsKey("role_2") + assert item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_CASE_DEFAULT_HEADERS.attributeId).rawValue == "meta-title,meta-title" + assert item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_TASK_DEFAULT_HEADERS.attributeId).rawValue == "meta-title,meta-title" + + assert filter.dataSet.get("filter").filterMetadata["filterType"] == "Case" + assert filter.dataSet.get("filter").allowedNets == ["filter", "preference_item"] + assert filter.dataSet.get("filter").rawValue == "processIdentifier:filter OR processIdentifier:preference_item" + assert filter.dataSet.get("filter_type").rawValue == "Case" assert leafNode != null Case testFolder = findCasesElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.${MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId}.textValue.keyword:\"/netgrif/test\"", PageRequest.of(0, 1))[0] @@ -110,14 +72,14 @@ class MenuItemApiTest { assert testFolder != null && testNode != null assert testFolder.uriNodeId == testNode.stringId - assert testFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId].value == [netgrifFolder.stringId] - assert (testFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as ArrayList).contains(item.stringId) - assert item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId].value == [testFolder.stringId] + assert testFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId).rawValue == [netgrifFolder.stringId] + assert (testFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId).rawValue as ArrayList).contains(item.stringId) + assert item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId).rawValue == [testFolder.stringId] assert netgrifFolder.uriNodeId == netgrifNode.stringId - assert netgrifFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId].value == [rootFolder.stringId] - assert (netgrifFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as ArrayList).contains(testFolder.stringId) - assert rootFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId].value == [] - assert (rootFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as ArrayList).contains(netgrifFolder.stringId) + assert netgrifFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId).rawValue == [rootFolder.stringId] + assert (netgrifFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId).rawValue as ArrayList).contains(testFolder.stringId) + assert rootFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId).rawValue == [] + assert (rootFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId).rawValue as ArrayList).contains(netgrifFolder.stringId) } @Test @@ -126,26 +88,26 @@ class MenuItemApiTest { Thread.sleep(3000) def newUri = uriService.getOrCreate("/netgrif/test_new", UriContentType.DEFAULT) caze = setData(caze, new DataSet([ - "uri" : newUri.uriPath, - "title" : "CHANGED FILTER", - "allowed_nets" : "filter", - "query" : "processIdentifier:filter", - "type" : "Case", - "icon" : "", - "change_filter_and_menu": "0" + "uri" : new TextField(newUri.uriPath), + "title" : new TextField("CHANGED FILTER"), + "allowed_nets" : new TextField("filter"), + "query" : new TextField("processIdentifier:filter"), +// "type" : "Case", + "icon" : new TextField(""), + "change_filter_and_menu": new ButtonField(rawValue: 0) ])) Case item = getMenuItem(caze) Case filter = getFilter(caze) - assert item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_MENU_NAME.attributeId].value.toString() == "CHANGED FILTER" - assert item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_ALLOWED_ROLES.attributeId].options.entrySet()[0].key.contains("role_2") - assert item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CASE_DEFAULT_HEADERS.attributeId].value == "meta-title,meta-title,meta-title" - assert item.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_TASK_DEFAULT_HEADERS.attributeId].value == "meta-title,meta-title,meta-title" + assert item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_MENU_NAME.attributeId).rawValue.toString() == "CHANGED FILTER" + assert item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_ALLOWED_ROLES.attributeId).options.entrySet()[0].key.contains("role_2") + assert item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_CASE_DEFAULT_HEADERS.attributeId).rawValue == "meta-title,meta-title,meta-title" + assert item.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_TASK_DEFAULT_HEADERS.attributeId).rawValue == "meta-title,meta-title,meta-title" assert item.uriNodeId == newUri.stringId - assert filter.dataSet["filter"].allowedNets == ["filter"] - assert filter.dataSet["filter"].filterMetadata["defaultSearchCategories"] == false - assert filter.dataSet["filter"].value == "processIdentifier:filter" + assert filter.dataSet.get("filter").allowedNets == ["filter"] + assert filter.dataSet.get("filter").filterMetadata["defaultSearchCategories"] == false + assert filter.dataSet.get("filter").rawValue == "processIdentifier:filter" } @Test @@ -163,19 +125,19 @@ class MenuItemApiTest { @Test void testMoveMenuItem() { Case apiCase = createMenuItem("/netgrif/test") - String viewId = apiCase.dataSet["menu_stringId"].value + String viewId = apiCase.dataSet.get("menu_stringId").rawValue apiCase = createMenuItem("/netgrif2/test2", "new_menu_item2") - String viewId2 = apiCase.dataSet["menu_stringId"].value + String viewId2 = apiCase.dataSet.get("menu_stringId").rawValue // move view Thread.sleep(2000) - apiCase = setData(apiCase, [ - "move_dest_uri" : "/netgrif2", - "move_item_id" : viewId, - "move_folder_path": null, - "move_item" : "0" - ]) + apiCase = setData(apiCase, new DataSet([ + "move_dest_uri" : new TextField("/netgrif2"), + "move_item_id" : new TextField(viewId), + "move_folder_path": new TextField(null), + "move_item" : new ButtonField(rawValue: 0) + ])) Case viewCase = workflowService.findOne(viewId) Thread.sleep(2000) @@ -184,47 +146,47 @@ class MenuItemApiTest { Case folderCase = findCasesElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.${MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId}.textValue:\"/netgrif2\"", PageRequest.of(0, 1))[0] assert viewCase.uriNodeId == node.stringId - ArrayList childIds = folderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as ArrayList + ArrayList childIds = folderCase.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId).rawValue as ArrayList assert childIds.contains(viewId) && childIds.size() == 2 // cyclic move assertThrows(IllegalArgumentException.class, () -> { - setData(apiCase, [ - "move_dest_uri" : "/netgrif2/cyclic", - "move_item_id" : null, - "move_folder_path": "/netgrif2", - "move_item" : "0" - ]) + setData(apiCase, new DataSet([ + "move_dest_uri" : new TextField("/netgrif2/cyclic"), + "move_item_id" : new TextField(null), + "move_folder_path": new TextField("/netgrif2"), + "move_item" : new ButtonField(rawValue: 0) + ])) }) // move folder - setData(apiCase, [ - "move_dest_uri" : "/netgrif/test3", - "move_item_id" : null, - "move_folder_path": "/netgrif2", - "move_item" : "0" - ]) + setData(apiCase, new DataSet([ + "move_dest_uri" : new TextField("/netgrif/test3"), + "move_item_id" : new TextField(null), + "move_folder_path": new TextField("/netgrif2"), + "move_item" : new ButtonField(rawValue: 0) + ])) Thread.sleep(2000) folderCase = findCasesElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.${MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId}.textValue:\"/netgrif/test3\"", PageRequest.of(0, 1))[0] Case folderCase2 = findCasesElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.${MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId}.textValue:\"/netgrif\"", PageRequest.of(0, 1))[0] - assert folderCase != null && folderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId].value == [folderCase2.stringId] + assert folderCase != null && folderCase.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId).rawValue == [folderCase2.stringId] folderCase = findCasesElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.${MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId}.textValue:\"/netgrif/test3/netgrif2\"", PageRequest.of(0, 1))[0] assert folderCase != null node = uriService.findByUri("/netgrif/test3") assert node != null assert folderCase.uriNodeId == node.stringId - assert folderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId].value == "/netgrif/test3/netgrif2" + assert folderCase.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId).rawValue == "/netgrif/test3/netgrif2" - childIds = folderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as ArrayList + childIds = folderCase.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId).rawValue as ArrayList assert childIds.size() == 2 folderCase = workflowService.findOne(childIds[0]) node = uriService.findByUri("/netgrif/test3/netgrif2") - assert folderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId].value == "/netgrif/test3/netgrif2/test2" + assert folderCase.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId).rawValue == "/netgrif/test3/netgrif2/test2" assert folderCase.uriNodeId == node.stringId viewCase = workflowService.findOne(viewId2) @@ -236,57 +198,60 @@ class MenuItemApiTest { void testDuplicateMenuItem() { String starterUri = "/netgrif/test" Case apiCase = createMenuItem(starterUri, "new_menu_item") - String itemId = apiCase.dataSet["menu_stringId"].value + String itemId = apiCase.dataSet.get("menu_stringId").rawValue Case origin = workflowService.findOne(itemId) - Case testFolder = workflowService.findOne((origin.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId].value as ArrayList)[0]) + Case testFolder = workflowService.findOne((origin.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId).rawValue as ArrayList)[0]) String newTitle = "New title" String newIdentifier = "new_identifier" - String duplicateTaskId = testFolder.tasks.find { it.transition == "duplicate_item" }.task - taskService.assignTask(duplicateTaskId) + String duplicateTaskId = testFolder.getTaskStringId("duplicate_item") + taskService.assignTask(new TaskParams(duplicateTaskId)) assertThrows(IllegalArgumentException.class, () -> { - testFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_TITLE.attributeId].value = new I18nString("") - testFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_IDENTIFIER.attributeId].value = newIdentifier + testFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_TITLE.attributeId).rawValue = new I18nString("") + testFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_IDENTIFIER.attributeId).rawValue = newIdentifier testFolder = workflowService.save(testFolder) - taskService.finishTask(duplicateTaskId) + taskService.finishTask(new TaskParams(duplicateTaskId)) }) assertThrows(IllegalArgumentException.class, () -> { - testFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_TITLE.attributeId].value = new I18nString(newTitle) - testFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_IDENTIFIER.attributeId].value = "new_menu_item" + testFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_TITLE.attributeId).rawValue = new I18nString(newTitle) + testFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_IDENTIFIER.attributeId).rawValue = "new_menu_item" testFolder = workflowService.save(testFolder) - taskService.finishTask(duplicateTaskId) + taskService.finishTask(new TaskParams(duplicateTaskId)) }) - testFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_TITLE.attributeId].value = new I18nString(newTitle) - testFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_IDENTIFIER.attributeId].value = newIdentifier + testFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_TITLE.attributeId).rawValue = new I18nString(newTitle) + testFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_IDENTIFIER.attributeId).rawValue = newIdentifier testFolder = workflowService.save(testFolder) - taskService.finishTask(duplicateTaskId) + taskService.finishTask(new TaskParams(duplicateTaskId)) - Case duplicated = workflowService.searchOne(QCase.case$.processIdentifier.eq("preference_item").and(QCase.case$.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_IDENTIFIER.attributeId).value.eq(newIdentifier))) - assert duplicated != null + Thread.sleep(2000) + List duplicatedAsList = findCasesElastic(String.format("processIdentifier:preference_item AND dataSet.%s.fulltextValue:%s", + MenuItemConstants.PREFERENCE_ITEM_FIELD_IDENTIFIER.attributeId, newIdentifier), PageRequest.of(0, 1)) + assert duplicatedAsList.size() == 1 + Case duplicated = duplicatedAsList.get(0) UriNode leafNode = uriService.findByUri("/netgrif/" + newIdentifier) assert duplicated.uriNodeId == testFolder.uriNodeId assert leafNode != null - assert duplicated.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_TITLE.attributeId].value == null - assert duplicated.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_IDENTIFIER.attributeId].value == null + assert duplicated.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_TITLE.attributeId).rawValue == null + assert duplicated.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_DUPLICATE_IDENTIFIER.attributeId).rawValue == null assert duplicated.title == newTitle - assert duplicated.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_MENU_NAME.attributeId].value == new I18nString(newTitle) - assert duplicated.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_IDENTIFIER.attributeId].value == newIdentifier - assert duplicated.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId].value == "/netgrif/" + newIdentifier - assert duplicated.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value == [] - assert duplicated.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_HAS_CHILDREN.attributeId].value == false + assert duplicated.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_MENU_NAME.attributeId).rawValue == new I18nString(newTitle) + assert duplicated.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_IDENTIFIER.attributeId).rawValue == newIdentifier + assert duplicated.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId).rawValue == "/netgrif/" + newIdentifier + assert duplicated.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId).rawValue == [] + assert duplicated.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_HAS_CHILDREN.attributeId).rawValue == false assert duplicated.activePlaces["initialized"] == 1 } List findCasesElastic(String query, Pageable pageable) { CaseSearchRequest request = new CaseSearchRequest() request.query = query - List result = elasticCaseService.search([request], userService.system.transformToLoggedUser(), pageable, LocaleContextHolder.locale, false).content + List result = elasticCaseService.search([request], superCreator.loggedSuper.activeActorId, pageable, LocaleContextHolder.locale, false).content return result } @@ -310,20 +275,20 @@ class MenuItemApiTest { void testRemoveMenuItem() { String starterUri = "/netgrif/test" Case apiCase = createMenuItem(starterUri, "new_menu_item") - String leafItemId = apiCase.dataSet["menu_stringId"].value + String leafItemId = apiCase.dataSet.get("menu_stringId").rawValue Case testFolder = findCasesElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.${MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId}.textValue:\"/netgrif/test\"", PageRequest.of(0, 1))[0] - String netgrifFolderId = (testFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId].value as ArrayList)[0] + String netgrifFolderId = (testFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID.attributeId).rawValue as ArrayList)[0] Case netgrifFolder = workflowService.findOne(netgrifFolderId) - assert (netgrifFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as ArrayList).contains(testFolder.stringId) + assert (netgrifFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId).rawValue as ArrayList).contains(testFolder.stringId) assert workflowService.findOne(testFolder.stringId) != null assert workflowService.findOne(leafItemId) != null - workflowService.deleteCase(testFolder) + workflowService.deleteCase(new DeleteCaseParams(testFolder)) sleep(2000) netgrifFolder = workflowService.findOne(netgrifFolderId) - assert !(netgrifFolder.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as ArrayList).contains(testFolder.stringId) + assert !(netgrifFolder.dataSet.get(MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId).rawValue as ArrayList).contains(testFolder.stringId) assertThrows(IllegalArgumentException.class, () -> { workflowService.findOne(testFolder.stringId) }) @@ -345,7 +310,7 @@ class MenuItemApiTest { } def setData(Case caze, DataSet dataSet) { - dataService.setData(caze.tasks["t1"].taskStringId, dataSet, superCreator.superUser) + dataService.setData(new SetDataParams(caze.tasks["t1"].taskStringId, dataSet, superCreator.loggedSuper.activeActorId)) return workflowService.findOne(caze.stringId) } } diff --git a/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy index c599bbc6d33..927140ad2e4 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy @@ -2,21 +2,20 @@ package com.netgrif.application.engine.action import com.netgrif.application.engine.ApplicationEngine import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.domain.repositories.UserRepository +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authorization.domain.repositories.ProcessRoleRepository +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService import com.netgrif.application.engine.configuration.properties.SuperAdminConfiguration import com.netgrif.application.engine.importer.service.Importer -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository +import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator -import groovy.json.JsonOutput -import org.junit.Assert import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -24,8 +23,6 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc import org.springframework.boot.test.context.SpringBootTest import org.springframework.data.mongodb.core.MongoTemplate -import org.springframework.hateoas.MediaTypes -import org.springframework.http.MediaType import org.springframework.mock.web.MockHttpServletRequest import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.core.Authentication @@ -34,16 +31,10 @@ import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.TestPropertySource import org.springframework.test.context.junit.jupiter.SpringExtension import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.result.MockMvcResultMatchers import org.springframework.test.web.servlet.setup.MockMvcBuilders import org.springframework.web.context.WebApplicationContext -import static org.hamcrest.core.StringContains.containsString -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @@ -69,10 +60,7 @@ class RemoveActionTest { private MongoTemplate template @Autowired - private UserRepository userRepository - - @Autowired - private ProcessRoleRepository processRoleRepository + private ProcessRoleRepository roleRepository @Autowired private Importer importer @@ -92,8 +80,14 @@ class RemoveActionTest { @Autowired private SuperAdminConfiguration configuration + @Autowired + private IRoleService roleService + + @Autowired + private IIdentityService identityService + private MockMvc mvc - private PetriNet petriNet + private Process petriNet private Authentication auth @BeforeEach @@ -105,62 +99,66 @@ class RemoveActionTest { .apply(springSecurity()) .build() - def net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/removeRole_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null + def net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/removeRole_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + assert net.getProcess() != null - this.petriNet = net.getNet() + this.petriNet = net.getProcess() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), - [auths.get("user")] as Authority[], - [] as ProcessRole[]) - auth = new UsernamePasswordAuthenticationToken(configuration.email, configuration.password) + Identity identity = importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Test")) + .lastname(new TextField("Integration")) + .password(new TextField(USER_PASSWORD)) + .username(new TextField(USER_EMAIL)) + .build(), new ArrayList<>()) + auth = new UsernamePasswordAuthenticationToken(identity.toSession(), configuration.password) auth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())); } @Test void addAndRemoveRole() { - User user = userRepository.findByEmail(USER_EMAIL) - String adminRoleId = petriNet.getRoles().find { it.value.name.defaultValue == "admin" }.key - - //Has no role, we assign role admin - def content = JsonOutput.toJson([adminRoleId]) - String userId = user.getStringId() - - mvc.perform(post(ROLE_API.replace("{}", userId)) - .accept(MediaTypes.HAL_JSON_VALUE) - .content(content) - .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE) - .with(csrf().asHeader()) - .with(authentication(this.auth))) - .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.content().string(containsString("Selected roles assigned to user"))) - - User updatedUser = userRepository.findByEmail(USER_EMAIL) - Set roles = updatedUser.getProcessRoles() - - String managerRoleId = processRoleRepository.findAllByName_DefaultValue("manager")?.first()?.stringId - - assert roles.find { it.getStringId() == adminRoleId } - assert roles.find { it.getStringId() == managerRoleId } - - //On frontend user had two roles admin and manage, and admin was removed, so now to the backend - //only manager role came, and as part of admin action, this one should get removed inside action - content = JsonOutput.toJson([managerRoleId]) - - mvc.perform(post(ROLE_API.replace("{}", userId)) - .accept(MediaTypes.HAL_JSON_VALUE) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .with(csrf().asHeader()) - .with(authentication(this.auth))) - .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.content().string(containsString("Selected roles assigned to user"))) - - updatedUser = userRepository.findByEmail(USER_EMAIL) - roles = updatedUser.getProcessRoles() - - Assert.assertNull(roles.find { it.stringId == adminRoleId }) - Assert.assertNotNull(roles.find { it.stringId == managerRoleId }) + // todo: release/8.0.0 +// User user = userRepository.findByEmail(USER_EMAIL) +// String adminRoleId = petriNet.getRoles().find { it.value.name.defaultValue == "admin" }.key +// +// //Has no role, we assign role admin +// def content = JsonOutput.toJson([adminRoleId]) +// String userId = user.getStringId() +// +// mvc.perform(post(ROLE_API.replace("{}", userId)) +// .accept(MediaTypes.HAL_JSON_VALUE) +// .content(content) +// .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE) +// .with(csrf().asHeader()) +// .with(authentication(this.auth))) +// .andExpect(status().isOk()) +// .andExpect(MockMvcResultMatchers.content().string(containsString("Selected roles assigned to user"))) +// +// User updatedUser = userRepository.findByEmail(USER_EMAIL) +// Set roles = updatedUser.getRoles() +// +// String managerRoleId = roleRepository.findAllByName_DefaultValue("manager")?.first()?.stringId +// +// assert roles.find { it.getStringId() == adminRoleId } +// assert roles.find { it.getStringId() == managerRoleId } +// +// //On frontend user had two roles admin and manage, and admin was removed, so now to the backend +// //only manager role came, and as part of admin action, this one should get removed inside action +// content = JsonOutput.toJson([managerRoleId]) +// +// mvc.perform(post(ROLE_API.replace("{}", userId)) +// .accept(MediaTypes.HAL_JSON_VALUE) +// .content(content) +// .contentType(MediaType.APPLICATION_JSON) +// .with(csrf().asHeader()) +// .with(authentication(this.auth))) +// .andExpect(status().isOk()) +// .andExpect(MockMvcResultMatchers.content().string(containsString("Selected roles assigned to user"))) +// +// updatedUser = userRepository.findByEmail(USER_EMAIL) +// roles = updatedUser.getRoles() +// +// Assert.assertNull(roles.find { it.stringId == adminRoleId }) +// Assert.assertNotNull(roles.find { it.stringId == managerRoleId }) } } diff --git a/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy deleted file mode 100644 index 39540c970fe..00000000000 --- a/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy +++ /dev/null @@ -1,408 +0,0 @@ -package com.netgrif.application.engine.auth - -import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.IUser -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.importer.service.AllDataConfiguration -import com.netgrif.application.engine.importer.service.Importer -import com.netgrif.application.engine.petrinet.domain.PetriNet -import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.dataset.Field -import com.netgrif.application.engine.petrinet.domain.dataset.UserListField -import com.netgrif.application.engine.petrinet.domain.dataset.UserListFieldValue -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.startup.SuperCreator -import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.TaskPair -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome -import com.netgrif.application.engine.workflow.service.interfaces.IDataService -import com.netgrif.application.engine.workflow.service.interfaces.ITaskAuthorizationService -import com.netgrif.application.engine.workflow.service.interfaces.ITaskService -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService -import com.netgrif.application.engine.workflow.web.responsebodies.DataSet -import groovy.json.JsonOutput -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.http.MediaType -import org.springframework.security.core.Authentication -import org.springframework.test.context.ActiveProfiles -import org.springframework.test.context.junit.jupiter.SpringExtension -import org.springframework.test.web.servlet.MockMvc -import org.springframework.web.context.WebApplicationContext - -import static org.springframework.http.MediaType.APPLICATION_JSON -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status - -@SpringBootTest -@ActiveProfiles(["test"]) -@ExtendWith(SpringExtension.class) -class TaskAuthorizationServiceTest { - - private static final String ASSIGN_TASK_URL = "/api/task/assign/" - private static final String DELEGATE_TASK_URL = "/api/task/delegate/" - private static final String FINISH_TASK_URL = "/api/task/finish/" - private static final String CANCEL_TASK_URL = "/api/task/cancel/" - private static final String SET_DATA_URL_TEMPLATE = "/api/task/%s/data" - private static final String SET_FILE_URL_TEMPLATE = "/api/task/%s/file/%s" - - private static final String USER_WITH_ROLE_EMAIL = "role@test.com" - private static final String USER_WITHOUT_ROLE_EMAIL = "norole@test.com" - private static final String ADMIN_USER_EMAIL = "admin@test.com" - private static final String USER_EMAIL = "user123987645@test.com" - - private MockMvc mvc - - private PetriNet net - private PetriNet netWithUserRefs - private IUser testUser - - private String userId - - private Authentication userWithRoleAuth - private Authentication userWithoutRoleAuth - private Authentication adminAuth - - @Autowired - private Importer importer - - @Autowired - private WebApplicationContext wac - - @Autowired - private ImportHelper importHelper - - @Autowired - private IPetriNetService petriNetService - - @Autowired - private ITaskAuthorizationService taskAuthorizationService - - @Autowired - private IUserService userService - - @Autowired - private IWorkflowService workflowService - - @Autowired - TestHelper testHelper - - @Autowired - private ITaskService taskService - - @Autowired - private SuperCreator superCreator - - @Autowired - private IDataService dataService - - private String taskId - private String taskId2 - - @BeforeEach - void init() { - testHelper.truncateDbs() - ImportPetriNetEventOutcome net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/task_authorization_service_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null - this.net = net.getNet() - - ImportPetriNetEventOutcome netWithUserRefs = petriNetService.importPetriNet(new FileInputStream("src/test/resources/task_authorization_service_test_with_userRefs.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert netWithUserRefs.getNet() != null - this.netWithUserRefs = netWithUserRefs.getNet() - - def auths = importHelper.createAuthorities(["user": Authority.user]) - testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], - [] as ProcessRole[] - ) - } - - - @Test - void testTaskAuthorizationService() { - def tests = [ - { -> testAssignAuthorization() }, - { -> testDelegateAuthorization() }, - { -> testFinishAuthorization() }, - { -> testCancelAuthorization() }, - { -> testSetDataAuthorization() }, - ] - } - - void testAssignAuthorization() { - mvc.perform(get(ASSIGN_TASK_URL + taskId) - .with(authentication(userWithoutRoleAuth))) - .andExpect(status().is4xxClientError()) - mvc.perform(get(ASSIGN_TASK_URL + taskId) - .with(authentication(userWithRoleAuth))) - .andExpect(status().isOk()) - mvc.perform(get(ASSIGN_TASK_URL + taskId2) - .with(authentication(adminAuth))) - .andExpect(status().isOk()) - } - - void testDelegateAuthorization() { - mvc.perform(post(DELEGATE_TASK_URL + taskId) - .content(userId.toString()) - .contentType(MediaType.TEXT_PLAIN_VALUE) - .with(authentication(this.userWithoutRoleAuth))) - .andExpect(status().isForbidden()) - mvc.perform(post(DELEGATE_TASK_URL + taskId) - .content(userId.toString()) - .contentType(MediaType.TEXT_PLAIN_VALUE) - .with(authentication(this.userWithRoleAuth))) - .andExpect(status().isOk()) - mvc.perform(post(DELEGATE_TASK_URL + taskId2) - .content(userId.toString()) - .contentType(MediaType.TEXT_PLAIN_VALUE) - .with(authentication(this.adminAuth))) - .andExpect(status().isOk()) - } - - void testFinishAuthorization() { - mvc.perform(get(ASSIGN_TASK_URL + taskId) - .with(authentication(this.userWithRoleAuth))) - .andExpect(status().isOk()) - mvc.perform(get(ASSIGN_TASK_URL + taskId2) - .with(authentication(this.userWithRoleAuth))) - .andExpect(status().isOk()) - - mvc.perform(get(FINISH_TASK_URL + taskId) - .with(authentication(this.userWithoutRoleAuth))) - .andExpect(status().isForbidden()) - mvc.perform(get(FINISH_TASK_URL + taskId) - .with(authentication(this.userWithRoleAuth))) - .andExpect(status().isOk()) - mvc.perform(get(FINISH_TASK_URL + taskId2) - .with(authentication(this.adminAuth))) - .andExpect(status().isOk()) - } - - void testCancelAuthorization() { - mvc.perform(get(ASSIGN_TASK_URL + taskId) - .with(authentication(this.userWithRoleAuth))) - .andExpect(status().isOk()) - mvc.perform(get(ASSIGN_TASK_URL + taskId2) - .with(authentication(this.userWithRoleAuth))) - .andExpect(status().isOk()) - - mvc.perform(get(CANCEL_TASK_URL + taskId) - .with(authentication(this.userWithoutRoleAuth))) - .andExpect(status().isForbidden()) - mvc.perform(get(CANCEL_TASK_URL + taskId) - .with(authentication(this.userWithRoleAuth))) - .andExpect(status().isOk()) - mvc.perform(get(CANCEL_TASK_URL + taskId2) - .with(authentication(this.adminAuth))) - .andExpect(status().isOk()) - } - - void testSetDataAuthorization() { - mvc.perform(get(ASSIGN_TASK_URL + taskId) - .with(authentication(this.userWithRoleAuth))) - .andExpect(status().isOk()) - mvc.perform(get(ASSIGN_TASK_URL + taskId2) - .with(authentication(this.userWithRoleAuth))) - .andExpect(status().isOk()) - - // TODO: release/8.0.0 change to dataset? - def body = JsonOutput.toJson([ - text: [ - value: "Helo world", - type : "text" - ] - ]) - - mvc.perform(post(String.format(SET_DATA_URL_TEMPLATE, taskId)) - .content(body) - .contentType(APPLICATION_JSON) - .with(authentication(this.userWithoutRoleAuth))) - .andExpect(status().isForbidden()) - mvc.perform(post(String.format(SET_DATA_URL_TEMPLATE, taskId)) - .content(body) - .contentType(APPLICATION_JSON) - .with(authentication(this.userWithRoleAuth))) - .andExpect(status().isOk()) - mvc.perform(post(String.format(SET_DATA_URL_TEMPLATE, taskId2)) - .content(body) - .contentType(APPLICATION_JSON) - .with(authentication(this.adminAuth))) - .andExpect(status().isOk()) - } - -// TODO 14.8.2020 test for file upload endpoint - -// void testSetFileAuthorization() { -// mvc.perform(get(ASSIGN_TASK_URL + taskId) -// .with(authentication(this.userWithRoleAuth))) -// .andExpect(status().isOk()) -// mvc.perform(get(ASSIGN_TASK_URL + taskId2) -// .with(authentication(this.userWithRoleAuth))) -// .andExpect(status().isOk()) -// -// MockMultipartFile file = new MockMultipartFile("data", "filename.txt", "text/plain", "some xml".getBytes()); -// -// mvc.perform(multipart(String.format(SET_FILE_URL_TEMPLATE, taskId, "file")) -// .file(file) -// .characterEncoding("UTF-8") -// .with(authentication(this.userWithoutRoleAuth))) -// .andExpect(status().isForbidden()) -// mvc.perform(multipart(String.format(SET_FILE_URL_TEMPLATE, taskId, "file")) -// .file(file) -// .characterEncoding("UTF-8") -// .with(authentication(this.userWithRoleAuth))) -// .andExpect(status().isOk()) -// mvc.perform(multipart(String.format(SET_FILE_URL_TEMPLATE, taskId2, "file")) -// .file(file) -// .characterEncoding("UTF-8") -// .contentType(APPLICATION_JSON) -// .with(authentication(this.adminAuth))) -// .andExpect(status().isOk()) -// } - - @Test - void testCanAssign() { - ProcessRole positiveRole = this.net.getRoles().values().find(v -> v.getImportId() == "assign_pos_role") - userService.addRole(testUser, positiveRole.getStringId()) - Case case_ = workflowService.createCase(net.getStringId(), "Test assign", "", testUser.transformToLoggedUser()).getCase() - assert taskAuthorizationService.canCallAssign(testUser.transformToLoggedUser(), case_.getTaskStringId("1")) - userService.removeRole(testUser, positiveRole.getStringId()) - workflowService.deleteCase(case_.stringId) - } - - @Test - void testCanNotAssign() { - ProcessRole negativeRole = this.net.getRoles().values().find(v -> v.getImportId() == "assign_neg_role") - userService.addRole(testUser, negativeRole.getStringId()) - Case case_ = workflowService.createCase(net.getStringId(), "Test assign", "", testUser.transformToLoggedUser()).getCase() - assert !taskAuthorizationService.canCallAssign(testUser.transformToLoggedUser(), case_.getTaskStringId("1")) - userService.removeRole(testUser, negativeRole.getStringId()) - workflowService.deleteCase(case_.stringId) - } - - @Test - void testCanAssignWithUsersRef() { - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Test assign", "", testUser.transformToLoggedUser()).getCase() - String taskId = case_.getTaskStringId("1") - case_ = dataService.setData(taskId, new DataSet([ - "assign_pos_ul":new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(testUser.stringId)])) - ] as Map>), superCreator.getSuperUser()).getCase() - workflowService.save(case_) - sleep(4000) - - assert taskAuthorizationService.canCallAssign(testUser.transformToLoggedUser(), taskId) - workflowService.deleteCase(case_.stringId) - } - - @Test - void testCannotAssignWithUsersRef() { - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Test assign", "", testUser.transformToLoggedUser()).getCase() - String taskId = case_.getTaskStringId("1") - case_ = dataService.setData(taskId, new DataSet([ - "assign_neg_ul": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(testUser.stringId)])) - ] as Map>), superCreator.getSuperUser()).getCase() - sleep(4000) - - assert !taskAuthorizationService.canCallAssign(testUser.transformToLoggedUser(), taskId) - workflowService.deleteCase(case_.stringId) - } - - @Test - void testCanAssignWithNegRoleAndPosUsersRef() { - ProcessRole positiveRole = this.netWithUserRefs.getRoles().values().find(v -> v.getImportId() == "assign_pos_role") - userService.addRole(testUser, positiveRole.getStringId()) - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Test assign", "", testUser.transformToLoggedUser()).getCase() - String taskId = case_.getTaskStringId("1") - case_ = dataService.setData(taskId, new DataSet([ - "assign_pos_ul": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(testUser.stringId)])) - ] as Map>), superCreator.getLoggedSuper()).getCase() - sleep(4000) - - assert taskAuthorizationService.canCallAssign(testUser.transformToLoggedUser(), taskId) - userService.removeRole(testUser, positiveRole.getStringId()) - workflowService.deleteCase(case_.stringId) - } - - @Test - void testCanFinish() { - ProcessRole positiveRole = this.netWithUserRefs.getRoles().values().find(v -> v.getImportId() == "finish_pos_role") - userService.addRole(testUser, positiveRole.getStringId()) - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Test Finish", "", testUser.transformToLoggedUser()).getCase() - - String taskId = case_.getTaskStringId("1") - taskService.assignTask(testUser.transformToLoggedUser(), taskId) - assert taskAuthorizationService.canCallFinish(testUser.transformToLoggedUser(), taskId) - userService.removeRole(testUser, positiveRole.getStringId()) - workflowService.deleteCase(case_.stringId) - } - - @Test - void testCanNotFinish() { - ProcessRole negativeRole = this.netWithUserRefs.getRoles().values().find(v -> v.getImportId() == "finish_neg_role") - userService.addRole(testUser, negativeRole.getStringId()) - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Test Finish", "", testUser.transformToLoggedUser()).getCase() - - String taskId = case_.getTaskStringId("1") - taskService.assignTask(testUser.transformToLoggedUser(), taskId) - assert !taskAuthorizationService.canCallFinish(testUser.transformToLoggedUser(), taskId) - userService.removeRole(testUser, negativeRole.getStringId()) - workflowService.deleteCase(case_.stringId) - } - - @Test - void testCanFinishWithUsersRef() { - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Test Finish", "", testUser.transformToLoggedUser()).getCase() - String taskId = case_.getTaskStringId("1") - case_ = dataService.setData(taskId, new DataSet([ - "finish_pos_ul": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(testUser.stringId)])) - ] as Map>), superCreator.getSuperUser()).getCase() - sleep(4000) - - taskService.assignTask(testUser.transformToLoggedUser(), taskId) - assert taskAuthorizationService.canCallFinish(testUser.transformToLoggedUser(), taskId) - workflowService.deleteCase(case_.stringId) - } - - @Test - void testCannotFinishWithUsersRef() { - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Test Finish", "", testUser.transformToLoggedUser()).getCase() - String taskId = case_.getTaskStringId("1") - case_ = dataService.setData(taskId, new DataSet([ - "finish_neg_ul": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(testUser.stringId)])) - ] as Map>), superCreator.getSuperUser()).getCase() - sleep(4000) - - taskService.assignTask(testUser.transformToLoggedUser(), taskId) - assert !taskAuthorizationService.canCallFinish(testUser.transformToLoggedUser(), taskId) - workflowService.deleteCase(case_.stringId) - } - - @Test - void testCanFinishWithNegRoleAndPosUsersRef() { - ProcessRole positiveRole = this.netWithUserRefs.getRoles().values().find(v -> v.getImportId() == "finish_pos_role") - userService.addRole(testUser, positiveRole.getStringId()) - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Test Finish", "", testUser.transformToLoggedUser()).getCase() - String taskId = case_.getTaskStringId("1") - case_ = dataService.setData(taskId, new DataSet([ - "finish_pos_ul": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(testUser.stringId)])) - ] as Map>), superCreator.getSuperUser()).getCase() - sleep(4000) - - taskService.assignTask(testUser.transformToLoggedUser(), taskId) - assert taskAuthorizationService.canCallFinish(testUser.transformToLoggedUser(), taskId) - userService.removeRole(testUser, positiveRole.getStringId()) - workflowService.deleteCase(case_.stringId) - } - -} diff --git a/src/test/groovy/com/netgrif/application/engine/auth/UserServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/UserServiceTest.groovy deleted file mode 100644 index 1428ccd814d..00000000000 --- a/src/test/groovy/com/netgrif/application/engine/auth/UserServiceTest.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package com.netgrif.application.engine.auth - -import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.petrinet.domain.PetriNet -import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService -import com.netgrif.application.engine.startup.ImportHelper -import groovy.transform.CompileStatic -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.test.context.ActiveProfiles -import org.springframework.test.context.junit.jupiter.SpringExtension - -@ExtendWith(SpringExtension.class) -@ActiveProfiles(["test"]) -@SpringBootTest -@CompileStatic -class UserServiceTest { - - @Autowired - private TestHelper helper - - @Autowired - private ImportHelper importHelper - - @Autowired - private IUserService service - - @Autowired - private IProcessRoleService roleService - - @Test - @Disabled("Create functions or update test") - void removeRole() { - helper.truncateDbs() - - Optional netOptional = importHelper.createNet("role_test.xml", VersionType.MAJOR, service.system.transformToLoggedUser()) - assert netOptional.get() != null - - def net = netOptional.get() - def roles = roleService.findAll(net.stringId) - def roleCount = service.system.processRoles.size() - roles.each { - service.addRole(service.system, it.stringId) - } - assert service.system.processRoles.size() == roleCount + 3 - - roles.each { - service.removeRole(service.system, it.stringId) - } - assert service.system.processRoles.size() == roleCount - } -} \ No newline at end of file diff --git a/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy deleted file mode 100644 index 5ffca556d3f..00000000000 --- a/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy +++ /dev/null @@ -1,281 +0,0 @@ -package com.netgrif.application.engine.auth - -import com.netgrif.application.engine.ApplicationEngine -import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.IUser -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.petrinet.domain.PetriNet -import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.dataset.Field -import com.netgrif.application.engine.petrinet.domain.dataset.UserListField -import com.netgrif.application.engine.petrinet.domain.dataset.UserListFieldValue -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.service.ProcessRoleService -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.startup.SuperCreator -import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome -import com.netgrif.application.engine.workflow.service.interfaces.IDataService -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowAuthorizationService -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService -import com.netgrif.application.engine.workflow.web.responsebodies.DataSet -import groovy.json.JsonOutput -import groovy.json.JsonSlurper -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.security.core.Authentication -import org.springframework.security.web.authentication.WebAuthenticationDetails -import org.springframework.test.context.ActiveProfiles -import org.springframework.test.context.TestPropertySource -import org.springframework.test.context.junit.jupiter.SpringExtension -import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.MvcResult -import org.springframework.test.web.servlet.setup.MockMvcBuilders -import org.springframework.web.context.WebApplicationContext - -import static org.springframework.http.MediaType.APPLICATION_JSON -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication -import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status - -@ExtendWith(SpringExtension.class) -@ActiveProfiles(["test"]) -@SpringBootTest( - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = ApplicationEngine.class -) -@AutoConfigureMockMvc -@TestPropertySource( - locations = "classpath:application-test.properties" -) -class WorkflowAuthorizationServiceTest { - - private static final String CREATE_CASE_URL = "/api/workflow/case" - private static final String DELETE_CASE_URL = "/api/workflow/case/" - - private static final String USER_EMAIL = "user123987645@test.com" - private static final String ADMIN_EMAIL = "admin65489796451@test.com" - - private MockMvc mvc - - @Autowired - private WebApplicationContext wac - - @Autowired - private IPetriNetService petriNetService - - @Autowired - private SuperCreator superCreator - - @Autowired - private ImportHelper importHelper - - @Autowired - private IWorkflowAuthorizationService workflowAuthorizationService - - @Autowired - private IWorkflowService workflowService - - @Autowired - private IDataService dataService - - @Autowired - TestHelper testHelper - - @Autowired - private IUserService userService - - private PetriNet net - private PetriNet netWithUserRefs - - private IUser testUser - private Authentication testUserAuth - private Authentication adminAuth - - - @BeforeEach - void init() { - testHelper.truncateDbs() - mvc = MockMvcBuilders - .webAppContextSetup(wac) - .apply(springSecurity()) - .build() - - ImportPetriNetEventOutcome net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/workflow_authorization_service_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null - this.net = net.getNet() - - ImportPetriNetEventOutcome netWithUserRefs = petriNetService.importPetriNet(new FileInputStream("src/test/resources/workflow_authorization_service_test_with_userRefs.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert netWithUserRefs.getNet() != null - this.netWithUserRefs = netWithUserRefs.getNet() - - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")]as Authority[], - [] as ProcessRole[]) - testUserAuth = new UsernamePasswordAuthenticationToken(USER_EMAIL, "password") - testUserAuth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())); - - importHelper.createUser(new User(name: "Admin", surname: "User", email: ADMIN_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("admin")] as Authority[], - [] as ProcessRole[]) - adminAuth = new UsernamePasswordAuthenticationToken(ADMIN_EMAIL, "password") - adminAuth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())); - } - - @Test - void testDeleteCase() { - def body = JsonOutput.toJson([ - title: "test case", - netId: this.net.stringId, - color: "color" - ]) - - // fail without CREATE role permission - mvc.perform(post(CREATE_CASE_URL) - .content(body) - .contentType(APPLICATION_JSON) - .with(authentication(this.testUserAuth))) - .andExpect(status().is(403)) - ProcessRole positiveCreateRole = this.net.getRoles().values().find(v -> v.getImportId() == "create_pos_role") - userService.addRole(testUser, positiveCreateRole.getStringId()) - - // pass with CREATE role permission - def result = mvc.perform(post(CREATE_CASE_URL) - .content(body) - .contentType(APPLICATION_JSON) - .with(authentication(this.testUserAuth))) - .andExpect(status().isOk()) - .andReturn() - def response = parseResult(result) - String userCaseId1 = response.outcome.case.stringId - // fail without DELETE role permission - mvc.perform(delete(DELETE_CASE_URL + userCaseId1) - .with(authentication(this.testUserAuth))) - .andExpect(status().is(403)) - // pass with DELETE role permission - ProcessRole positiveDeleteRole = this.net.getRoles().values().find(v -> v.getImportId() == "delete_pos_role") - userService.addRole(testUser, positiveDeleteRole.getStringId()) - mvc.perform(delete(DELETE_CASE_URL + userCaseId1) - .with(authentication(this.testUserAuth))) - .andExpect(status().isOk()) - - result = mvc.perform(post(CREATE_CASE_URL) - .content(body) - .contentType(APPLICATION_JSON) - .with(authentication(this.testUserAuth))) - .andExpect(status().isOk()) - .andReturn() - response = parseResult(result) - String userCaseId2 = response.outcome.case.stringId - mvc.perform(delete(DELETE_CASE_URL + userCaseId2) - .with(authentication(this.adminAuth))) - .andExpect(status().isOk()) - - result = mvc.perform(post(CREATE_CASE_URL) - .content(body) - .contentType(APPLICATION_JSON) - .with(authentication(this.adminAuth))) - .andExpect(status().isOk()) - .andReturn() - response = parseResult(result) - String otherUserCaseId = response.outcome.case.stringId - mvc.perform(delete(DELETE_CASE_URL + otherUserCaseId) - .with(authentication(this.testUserAuth))) - .andExpect(status().isOk()) - } - - @Test - void testCanCallCreate() { - ProcessRole positiveCreateRole = this.net.getRoles().values().find(v -> v.getImportId() == "create_pos_role") - userService.addRole(testUser, positiveCreateRole.getStringId()) - assert workflowAuthorizationService.canCallCreate(testUser.transformToLoggedUser(), net.getStringId()) - userService.removeRole(testUser, positiveCreateRole.getStringId()) - } - - @Test - void testCanCallDelete() { - ProcessRole positiveDeleteRole = this.net.getRoles().values().find(v -> v.getImportId() == "delete_pos_role") - userService.addRole(testUser, positiveDeleteRole.getStringId()) - Case case_ = workflowService.createCase(net.getStringId(), "Test delete", "", testUser.transformToLoggedUser()).getCase() - assert workflowAuthorizationService.canCallDelete(testUser.transformToLoggedUser(), case_.getStringId()) - userService.removeRole(testUser, positiveDeleteRole.getStringId()) - } - - @Test - void testCanCallCreateFalse() { - ProcessRole positiveCreateRole = this.net.getRoles().values().find(v -> v.getImportId() == "create_neg_role") - userService.addRole(testUser, positiveCreateRole.getStringId()) - assert !workflowAuthorizationService.canCallCreate(testUser.transformToLoggedUser(), net.getStringId()) - userService.removeRole(testUser, positiveCreateRole.getStringId()) - } - - @Test - void testCanCallDeleteFalse() { - ProcessRole deleteRole = this.net.getRoles().values().find(v -> v.getImportId() == "delete_neg_role") - userService.addRole(testUser, deleteRole.getStringId()) - Case case_ = workflowService.createCase(net.getStringId(), "Test delete", "", testUser.transformToLoggedUser()).getCase() - assert !workflowAuthorizationService.canCallDelete(testUser.transformToLoggedUser(), case_.getStringId()) - userService.removeRole(testUser, deleteRole.getStringId()) - } - - - @Test - void testCanCallDeleteRoleFalseUserRefTrue() { - ProcessRole posDeleteRole = this.netWithUserRefs.getRoles().values().find(v -> v.getImportId() == "delete_pos_role") - ProcessRole negDeleteRole = this.netWithUserRefs.getRoles().values().find(v -> v.getImportId() == "delete_neg_role") - - userService.addRole(testUser, posDeleteRole.getStringId()) - userService.addRole(testUser, negDeleteRole.getStringId()) - - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Test delete", "", testUser.transformToLoggedUser()).getCase() - String taskId = case_.getTaskStringId("1") - case_ = dataService.setData(taskId, new DataSet([ - "pos_user_list": new UserListField(rawValue: new UserListFieldValue(userValues: [dataService.makeUserFieldValue(testUser.stringId)])), - ] as Map>), superCreator.getSuperUser()).getCase() - workflowService.save(case_) - - assert workflowAuthorizationService.canCallDelete(testUser.transformToLoggedUser(), case_.getStringId()) - - userService.removeRole(testUser, posDeleteRole.getStringId()) - userService.removeRole(testUser, negDeleteRole.getStringId()) - } - - @Test - void testCanCallDeleteRoleFalseUserRefTrueUserRefFalse() { - ProcessRole posDeleteRole = this.netWithUserRefs.getRoles().values().find(v -> v.getImportId() == "delete_pos_role") - ProcessRole negDeleteRole = this.netWithUserRefs.getRoles().values().find(v -> v.getImportId() == "delete_neg_role") - - userService.addRole(testUser, posDeleteRole.getStringId()) - userService.addRole(testUser, negDeleteRole.getStringId()) - - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Test delete", "", testUser.transformToLoggedUser()).getCase() - String taskId = case_.getTaskStringId("1") - case_ = dataService.setData(taskId, new DataSet([ - "pos_user_list": new UserListField(rawValue: new UserListFieldValue(userValues: [dataService.makeUserFieldValue(testUser.stringId)])), - "neg_user_list": new UserListField(rawValue: new UserListFieldValue(userValues: [dataService.makeUserFieldValue(testUser.stringId)])) - ] as Map>), superCreator.getSuperUser()).getCase() - - assert !workflowAuthorizationService.canCallDelete(testUser.transformToLoggedUser(), case_.getStringId()) - - userService.removeRole(testUser, posDeleteRole.getStringId()) - userService.removeRole(testUser, negDeleteRole.getStringId()) - } - - @SuppressWarnings("GrMethodMayBeStatic") - private def parseResult(MvcResult result) { - return (new JsonSlurper()).parseText(result.response.contentAsString) - } -} diff --git a/src/test/groovy/com/netgrif/application/engine/auth/AuthenticationControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/authentication/AuthenticationControllerTest.groovy similarity index 70% rename from src/test/groovy/com/netgrif/application/engine/auth/AuthenticationControllerTest.groovy rename to src/test/groovy/com/netgrif/application/engine/authentication/AuthenticationControllerTest.groovy index ecee3d32bfd..7cf3c9f219a 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/AuthenticationControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/authentication/AuthenticationControllerTest.groovy @@ -1,32 +1,26 @@ -package com.netgrif.application.engine.auth +package com.netgrif.application.engine.authentication import com.icegreen.greenmail.util.GreenMail import com.icegreen.greenmail.util.ServerSetup import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.repositories.AuthorityRepository -import com.netgrif.application.engine.auth.domain.repositories.UserRepository -import com.netgrif.application.engine.auth.web.AuthenticationController -import com.netgrif.application.engine.auth.web.requestbodies.NewUserRequest -import com.netgrif.application.engine.auth.web.requestbodies.RegistrationRequest +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authentication.web.AuthenticationController +import com.netgrif.application.engine.authentication.web.requestbodies.NewIdentityRequest +import com.netgrif.application.engine.authentication.web.requestbodies.RegistrationRequest import com.netgrif.application.engine.importer.service.Importer import com.netgrif.application.engine.mail.EmailType import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator -import groovy.transform.CompileStatic import org.jsoup.Jsoup import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest -import org.springframework.security.test.context.support.WithMockUser import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension @@ -40,7 +34,7 @@ import javax.mail.internet.MimeMultipart @SpringBootTest class AuthenticationControllerTest { - private static final String EMAIL = "tets@test.com" + private static final String EMAIL = "test@test.com" private static final String NAME = "name" private static final String SURNAME = "surname" private static final String PASSWORD = "password" @@ -58,13 +52,10 @@ class AuthenticationControllerTest { private ImportHelper importHelper @Autowired - private UserRepository userRepository + private IPetriNetService petriNetService @Autowired - private AuthorityRepository authorityRepository - - @Autowired - private IPetriNetService petriNetService + private IIdentityService identityService @Autowired private TestHelper testHelper @@ -80,17 +71,16 @@ class AuthenticationControllerTest { smtpServer = new GreenMail(new ServerSetup(2525, null, "smtp")) smtpServer.start() - def net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/insurance_portal_demo_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null - if (authorityRepository.count() == 0) { - importHelper.createAuthority(Authority.user) - } + def net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/insurance_portal_demo_test_new.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + assert net.getProcess() != null } @Test - @WithMockUser(roles = "ADMIN") +// @WithMockUser(roles = "ADMIN") void inviteTest() { - controller.invite(new NewUserRequest(email: EMAIL, groups: [] as Set, processRoles: [] as Set), null) + TestHelper.login(superCreator.superIdentity) + controller.invite(new NewIdentityRequest(email: EMAIL, groups: [] as Set, roles: [] as Set), null) MimeMessage[] messages = smtpServer.getReceivedMessages() assertMessageReceived(messages) @@ -98,10 +88,9 @@ class AuthenticationControllerTest { String content = getTextFromMimeMultipart(messages[0].content as MimeMultipart) String token = content.substring(content.indexOf("/signup/") + "/signup/".length(), content.lastIndexOf(" This is")) - controller.signup(new RegistrationRequest(token: token, name: NAME, surname: SURNAME, password: PASSWORD)) + controller.signup(new RegistrationRequest(token: token, firstname: NAME, lastname: SURNAME, password: PASSWORD)) - User user = userRepository.findByEmail(EMAIL) - assert user + assert identityService.existsByUsername(EMAIL) } @@ -116,7 +105,7 @@ class AuthenticationControllerTest { MimeMessage message = messages[0] - assert "noreply@netgrif.com".equalsIgnoreCase(message.getFrom()[0].toString()) + assert "test@example.com".equalsIgnoreCase(message.getFrom()[0].toString()) assert EmailType.REGISTRATION.getSubject().equalsIgnoreCase(message.getSubject()) } diff --git a/src/test/groovy/com/netgrif/application/engine/auth/LoginAttemptsTest.groovy b/src/test/groovy/com/netgrif/application/engine/authentication/LoginAttemptsTest.groovy similarity index 88% rename from src/test/groovy/com/netgrif/application/engine/auth/LoginAttemptsTest.groovy rename to src/test/groovy/com/netgrif/application/engine/authentication/LoginAttemptsTest.groovy index fea157b98fb..9349601aa2f 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/LoginAttemptsTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/authentication/LoginAttemptsTest.groovy @@ -1,11 +1,12 @@ -package com.netgrif.application.engine.auth +package com.netgrif.application.engine.authentication import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authorization.domain.ApplicationRole +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService import com.netgrif.application.engine.configuration.properties.SecurityLimitsProperties -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.petrinet.domain.dataset.TextField import com.netgrif.application.engine.startup.ImportHelper import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -37,7 +38,7 @@ class LoginAttemptsTest { public static final String USER_EMAIL = "test@mail.sk" public static final String USER_PASSWORD = "password" public static final String USER_BAD_PASSWORD = "totok" - public static final String LOGIN_URL = "/api/user/me" + public static final String LOGIN_URL = "/api/identity/me" private MockMvc mvc @@ -51,7 +52,13 @@ class LoginAttemptsTest { private ImportHelper importHelper @Autowired - private SecurityLimitsProperties securityLimitsProperties; + private IIdentityService identityService + + @Autowired + private IRoleService roleService + + @Autowired + private SecurityLimitsProperties securityLimitsProperties @BeforeEach void before() { @@ -61,10 +68,18 @@ class LoginAttemptsTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), - [auths.get("user"), auths.get("admin")] as Authority[], - [] as ProcessRole[]) + List appRoles = new ArrayList<>() + appRoles.add(roleService.findApplicationRoleByImportId("admin")) + appRoles.add(roleService.findApplicationRoleByImportId("default")) + identityService.createWithDefaultUser(IdentityParams.with() + .firstname(new TextField("Test")) + .lastname(new TextField("Integration")) + .username(new TextField(USER_EMAIL)) + .password(new TextField(USER_PASSWORD)) + .build()) + + Thread.sleep(2000) + TestHelper.logout() } diff --git a/src/test/groovy/com/netgrif/application/engine/auth/SecurityContextTest.groovy b/src/test/groovy/com/netgrif/application/engine/authentication/SecurityContextTest.groovy similarity index 55% rename from src/test/groovy/com/netgrif/application/engine/auth/SecurityContextTest.groovy rename to src/test/groovy/com/netgrif/application/engine/authentication/SecurityContextTest.groovy index 46b67ba44cc..9cd3bf272ee 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/SecurityContextTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/authentication/SecurityContextTest.groovy @@ -1,18 +1,15 @@ -package com.netgrif.application.engine.auth +package com.netgrif.application.engine.authentication import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.IUser -import com.netgrif.application.engine.auth.domain.LoggedUser -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.service.UserDetailsServiceImpl -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.petrinet.domain.PetriNet + +import com.netgrif.application.engine.authentication.service.UserDetailsServiceImpl + +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionDelegate import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService import com.netgrif.application.engine.security.service.ISecurityContextService -import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import groovy.transform.CompileStatic import org.junit.jupiter.api.BeforeEach @@ -25,8 +22,6 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension -import java.util.stream.Collectors; - @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @SpringBootTest @@ -43,57 +38,54 @@ class SecurityContextTest { private ActionDelegate delegate @Autowired - private IProcessRoleService processRoleService + private IRoleService roleService @Autowired private TestHelper testHelper - @Autowired - private IUserService userService - @Autowired private IPetriNetService petriNetService @Autowired private SuperCreator superCreator - private IUser user - - private PetriNet net + private Process net @BeforeEach void before() { testHelper.truncateDbs() - user = userService.save(new User('test@email.com', 'password', 'Test', 'User')) - assert user != null - - net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() - assert net != null +// user = userService.save(new User('test@email.com', 'password', 'Test', 'User')) +// assert user != null +// +// net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() +// assert net != null } @Test void addRole() { - Set roleIds = net.getRoles().keySet() - - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.transformToLoggedUser(), user.transformToLoggedUser().getPassword(), user.transformToLoggedUser().getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(token) - - // situation 1 - processRoleService.assignRolesToUser(user.getStringId(), roleIds, superCreator.getLoggedSuper()) - IUser updatedUser = userService.findById(user.getStringId()) - Set updatedUserRoles = updatedUser.getProcessRoles().stream().map(r -> r.getStringId()).collect(Collectors.toSet()) - assert ((LoggedUser) SecurityContextHolder.getContext().authentication.principal).getProcessRoles() != updatedUserRoles - - securityContextService.reloadSecurityContext(updatedUser.transformToLoggedUser()) - updatedUserRoles = updatedUser.getProcessRoles().stream().map(r -> r.getStringId()).collect(Collectors.toSet()) - assert ((LoggedUser) SecurityContextHolder.getContext().authentication.principal).getProcessRoles() == updatedUserRoles + // TODO: release/8.0.0 fix +// Set roleIds = net.getRoles().keySet() +// Set roleIds = [] +// +// UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.transformToLoggedUser(), user.transformToLoggedUser().getPassword(), user.transformToLoggedUser().getAuthorities()); +// SecurityContextHolder.getContext().setAuthentication(token) +// +// // situation 1 +// roleService.assignRolesToActor(user.getStringId(), roleIds) +// IUser updatedUser = userService.findById(user.getStringId()) +// Set updatedUserRoles = updatedUser.getRoles().stream().map(r -> r.getStringId()).collect(Collectors.toSet()) +// assert ((LoggedUser) SecurityContextHolder.getContext().authentication.principal).getRoles() != updatedUserRoles + +// securityContextService.reloadSecurityContext(updatedUser.transformToLoggedUser()) +// updatedUserRoles = updatedUser.getRoles().stream().map(r -> r.getStringId()).collect(Collectors.toSet()) +// assert ((LoggedUser) SecurityContextHolder.getContext().authentication.principal).getRoles() == updatedUserRoles // TODO: release/8.0.0 securityContextService.reloadSecurityContext(updatedUser.transformToLoggedUser()) // assert ((LoggedUser) SecurityContextHolder.getContext().authentication.principal).getProcessRoles() == updatedUser.getProcessRoles().stream().map(r -> r.getStringId()).collect(Collectors.toSet()) // // // situation 2 - // processRoleService.assignRolesToUser(user.getStringId(), Collections.singleton(roleIds.getAt(0)), superCreator.getLoggedSuper()) + // processRoleService.assignRolesToUser(user.getStringId(), Collections.singleton(roleIds.getAt(0)), superCreator.getLoggedSuper().getActiveActorId()) // updatedUser = userService.findById(user.getStringId(), false) // assert ((LoggedUser) SecurityContextHolder.getContext().authentication.principal).getProcessRoles() != updatedUser.getProcessRoles().stream().map(r -> r.getStringId()).collect(Collectors.toSet()) // diff --git a/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy b/src/test/groovy/com/netgrif/application/engine/business/InsuranceTest.groovy similarity index 89% rename from src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy rename to src/test/groovy/com/netgrif/application/engine/business/InsuranceTest.groovy index 438f8fe0222..9aa0a85ffe0 100644 --- a/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/business/InsuranceTest.groovy @@ -1,23 +1,22 @@ -package com.netgrif.application.engine.insurance.mvc +package com.netgrif.application.engine.business import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectWriter import com.netgrif.application.engine.ApplicationEngine import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.importer.service.Importer +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authorization.domain.ApplicationRole +import com.netgrif.application.engine.authorization.domain.Role import com.netgrif.application.engine.petrinet.domain.I18nString import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.dataset.* -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.authorization.domain.ProcessRole +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import com.netgrif.application.engine.workflow.web.responsebodies.DataSet import com.netgrif.application.engine.workflow.web.responsebodies.TaskDataSets import groovy.json.JsonOutput @@ -95,32 +94,18 @@ class InsuranceTest { private MockMvc mvc - @Autowired - private Importer importer - @Autowired private WebApplicationContext wac - @Autowired private ImportHelper importHelper - @Autowired private IPetriNetService petriNetService - @Autowired private SuperCreator superCreator - @Autowired - private IProcessRoleService processRoleService - - @Autowired - private IUserService userService - + private IRoleService roleService @Autowired private TestHelper testHelper - // TODO: NAE-1858 remove, for test only - @Autowired - private IWorkflowService workflowService @Autowired private ObjectMapper objectMapper @@ -133,20 +118,26 @@ class InsuranceTest { .apply(springSecurity()) .build() - def net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/insurance_portal_demo_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null + def net = petriNetService.importProcess(new ImportProcessParams(TestHelper.stream("insurance_portal_demo_test_new.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + assert net.getProcess() != null + + netId = net.getProcess().getStringId() - netId = net.getNet().getStringId() + List applicationRoles = new ArrayList<>() + applicationRoles.add(roleService.findApplicationRoleByImportId("default")) + applicationRoles.add(roleService.findApplicationRoleByImportId("admin")) + List processRoles = roleService.findAllProcessRolesByImportIds(["agent", "company"] as Set) + Identity identity = importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Test")) + .lastname(new TextField("Integration")) + .password(new TextField("password")) + .username(new TextField(USER_EMAIL)) + .build(), processRoles + applicationRoles as List) - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - def processRoles = importHelper.getProcessRolesByImportId(net.getNet(), ["agent": "1", "company": "2"]) - importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user"), auths.get("admin")] as Authority[], - [processRoles.get("agent"), processRoles.get("company")] as ProcessRole[]) - List roles = processRoleService.findAll(netId) - processRoleService.assignRolesToUser(userService.findByEmail(USER_EMAIL, false).stringId, roles.findAll { it.importId in ["1", "2"] }.collect { it.stringId } as Set, userService.getLoggedOrSystem().transformToLoggedUser()) + Thread.sleep(2000) - auth = new UsernamePasswordAuthenticationToken(USER_EMAIL, "password") + auth = new UsernamePasswordAuthenticationToken(identity.toSession(), "password") auth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())); objectWriter = objectMapper.writer().withDefaultPrettyPrinter() @@ -338,7 +329,6 @@ class InsuranceTest { "101001": new TextField(rawValue: "84105") ])) setData(new DataSet([ - "301005": new EnumerationField(rawValue: new I18nString("Bratislava")), "101002": new BooleanField(rawValue: false), "101003": new BooleanField(rawValue: false), "101004": new BooleanField(rawValue: false), diff --git a/src/test/groovy/com/netgrif/application/engine/business/RequestTest.groovy b/src/test/groovy/com/netgrif/application/engine/business/RequestTest.groovy new file mode 100644 index 00000000000..7cf94746bc5 --- /dev/null +++ b/src/test/groovy/com/netgrif/application/engine/business/RequestTest.groovy @@ -0,0 +1,331 @@ +package com.netgrif.application.engine.business + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.ObjectWriter +import com.netgrif.application.engine.ApplicationEngine +import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authorization.domain.ApplicationRole +import com.netgrif.application.engine.authorization.domain.ProcessRole +import com.netgrif.application.engine.authorization.domain.Role +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService +import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField +import com.netgrif.application.engine.petrinet.domain.dataset.NumberField +import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService +import com.netgrif.application.engine.startup.ImportHelper +import com.netgrif.application.engine.startup.SuperCreator +import com.netgrif.application.engine.workflow.domain.Case +import com.netgrif.application.engine.workflow.domain.State +import com.netgrif.application.engine.workflow.domain.Task +import com.netgrif.application.engine.workflow.service.interfaces.ITaskService +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService +import com.netgrif.application.engine.workflow.web.responsebodies.DataSet +import com.netgrif.application.engine.workflow.web.responsebodies.TaskDataSets +import groovy.json.JsonOutput +import groovy.json.JsonSlurper +import org.hamcrest.CoreMatchers +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.hateoas.MediaTypes +import org.springframework.http.MediaType +import org.springframework.mock.web.MockHttpServletRequest +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken +import org.springframework.security.core.Authentication +import org.springframework.security.web.authentication.WebAuthenticationDetails +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.context.TestPropertySource +import org.springframework.test.context.junit.jupiter.SpringExtension +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.MvcResult +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.web.context.WebApplicationContext + +import java.nio.charset.StandardCharsets + +import static com.netgrif.application.engine.workflow.domain.State.DISABLED +import static com.netgrif.application.engine.workflow.domain.State.ENABLED +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status + +@ExtendWith(SpringExtension.class) +@ActiveProfiles(["test"]) +@SpringBootTest( + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = ApplicationEngine.class +) +@AutoConfigureMockMvc +@TestPropertySource( + locations = "classpath:application-test.properties" +) +class RequestTest { + + @Test + void firstDepartmentTest() { + createCase("My request") + submitRequest(1_234d) + register() + firstDepartment() + answer() + assertRequest([ + "t1": DISABLED, + "t2": DISABLED, + "t3": DISABLED, + "t4": DISABLED, + "t5": DISABLED, + "t6": DISABLED, + "t7": DISABLED, + "t8": ENABLED, + "t9": ENABLED + ]) + } + + @Test + void secondDepartmentTest() { + createCase("My request") + submitRequest(2_345d) + register() + secondDepartment() + answer() + assertRequest([ + "t1": DISABLED, + "t2": DISABLED, + "t3": DISABLED, + "t4": DISABLED, + "t5": DISABLED, + "t6": DISABLED, + "t7": DISABLED, + "t8": ENABLED, + "t9": ENABLED + ]) + } + + void submitRequest(double customerId) { + searchTasks("t1") + assignTask() + setData(new DataSet([ + "name" : new TextField(rawValue: "John"), + "surname" : new TextField(rawValue: "Doe"), + "email" : new TextField(rawValue: "johndoe@email.com"), + "customer_id" : new NumberField(rawValue: customerId), + "request_text": new TextField(rawValue: "Please change my address") + ])) + finishTask() + } + + void register() { + searchTasks("t2") + assignTask() + setData(new DataSet([ + "request_origin": new EnumerationMapField(rawValue: "online") + ])) + finishTask() + } + + void firstDepartment() { + searchTasks("t4") + assignTask() + setData(DataSet.of("answer_department", new TextField(rawValue: "Address changed. 1st dpt"))) + finishTask() + } + + void secondDepartment() { + searchTasks("t7") + assignTask() + setData(DataSet.of("answer_department", new TextField(rawValue: "Address changed. 2nd dpt"))) + finishTask() + } + + void answer() { + searchTasks("t5") + assignTask() + setData(DataSet.of("answer_registration", new TextField(rawValue: "Your address was changed"))) + finishTask() + } + + void assertRequest(Map taskStates) { + Case requestCase = workflowService.findOne(caseId) + List requestTasks = taskService.findAllByCase(caseId) + + taskStates.each { String t, State state -> + assert requestCase.tasks[t].state == state + assert requestTasks.find { it.transitionId == t }.state == state + } + } + + void createCase(String title) { + def content = JsonOutput.toJson([ + title: title, + netId: netId, + color: "color" + ]) + def result = mvc.perform(post(CASE_CREATE_URL) + .accept(MediaTypes.HAL_JSON_VALUE) + .content(content) + .contentType(MediaType.APPLICATION_JSON_UTF8) + .with(csrf().asHeader()) + .with(authentication(auth))) + .andExpect(status().isOk()) + .andExpect(jsonPath('$.outcome.case.title', CoreMatchers.is(title))) + .andExpect(jsonPath('$.outcome.case.petriNetId', CoreMatchers.is(netId))) + .andReturn() + def response = parseResult(result) + caseId = response.outcome.case.stringId + } + + @SuppressWarnings("GrMethodMayBeStatic") + private def parseResult(MvcResult result) { + return (new JsonSlurper()).parseText(result.response.getContentAsString(StandardCharsets.UTF_8)) + } + + void assignTask() { + mvc.perform(get(TASK_ASSIGN_URL, taskId) + .accept(MediaTypes.HAL_JSON_VALUE) + .locale(Locale.forLanguageTag(LOCALE_SK)) + .with(csrf().asHeader()) + .with(authentication(this.auth))) + .andExpect(status().isOk()) + .andExpect(jsonPath('$.success', CoreMatchers.isA(String))) + .andReturn() + getData() + } + + void finishTask() { + mvc.perform(get(TASK_FINISH_URL, taskId) + .accept(MediaTypes.HAL_JSON_VALUE) + .locale(Locale.forLanguageTag(LOCALE_SK)) + .with(csrf().asHeader()) + .with(authentication(this.auth))) + .andExpect(status().isOk()) + .andExpect(jsonPath('$.success', CoreMatchers.isA(String))) + .andReturn() + } + + void getData() { + mvc.perform(get(TASK_DATA_URL, taskId) + .accept(MediaTypes.HAL_JSON_VALUE) + .locale(Locale.forLanguageTag(LOCALE_SK)) + .with(csrf().asHeader()) + .with(authentication(this.auth))) + .andExpect(status().isOk()) + .andReturn() + } + + void setData(DataSet dataSet) { + String content = objectWriter.writeValueAsString(new TaskDataSets([(taskId): dataSet])) + mvc.perform(post(TASK_DATA_URL, taskId) + .accept(MediaType.APPLICATION_JSON_VALUE) + .locale(Locale.forLanguageTag(LOCALE_SK)) + .content(content) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .with(csrf().asHeader()) + .with(authentication(this.auth))) + .andExpect(status().isOk()) + .andReturn() + getData() + } + + void searchTasks(String transitionId) { + def content = JsonOutput.toJson([ + query: "caseId: ${caseId}" + ]) + def result = mvc.perform(post(TASK_SEARCH_ELASTIC_URL) + .accept(MediaTypes.HAL_JSON_VALUE) + .locale(Locale.forLanguageTag(LOCALE_SK)) + .content(content) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .with(csrf().asHeader()) + .with(authentication(this.auth))) + .andExpect(status().isOk()) + .andReturn() + def response = parseResult(result) + taskId = response?._embedded?.tasks?.find { it.transitionId == transitionId }?.stringId + assert taskId != null + } + + private static final String CASE_CREATE_URL = "/api/workflow/case" + private static final String TASK_SEARCH_ELASTIC_URL = "/api/task/search_es?sort=priority&page=0&size=50" + private static final String TASK_ASSIGN_URL = "/api/task/assign/{id}" + private static final String TASK_FINISH_URL = "/api/task/finish/{id}" + private static final String TASK_DATA_URL = "/api/task/{id}/data" + private static final String USER_EMAIL = "test@test.com" + private static final String LOCALE_SK = "sk" + + private Authentication auth + private MockMvc mvc + + private WebApplicationContext wac + private TestHelper testHelper + private SuperCreator superCreator + private ImportHelper importHelper + private ObjectMapper objectMapper + private IPetriNetService petriNetService + private IRoleService roleService + private IWorkflowService workflowService + private ITaskService taskService + + @Autowired + RequestTest(WebApplicationContext wac, TestHelper testHelper, SuperCreator superCreator, ImportHelper importHelper, ObjectMapper objectMapper, IPetriNetService petriNetService, IRoleService roleService, IWorkflowService workflowService, ITaskService taskService) { + this.wac = wac + this.testHelper = testHelper + this.superCreator = superCreator + this.importHelper = importHelper + this.objectMapper = objectMapper + this.petriNetService = petriNetService + this.roleService = roleService + this.workflowService = workflowService + this.taskService = taskService + } + + private String caseId + private String netId + private String taskId + private ObjectWriter objectWriter + + @BeforeEach + void before() { + testHelper.truncateDbs() + + mvc = MockMvcBuilders + .webAppContextSetup(wac) + .apply(springSecurity()) + .build() + + def net = petriNetService.importProcess(new ImportProcessParams(TestHelper.stream("request.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) + assert net.getProcess() != null + + netId = net.getProcess().getStringId() + + List applicationRoles = new ArrayList<>() + applicationRoles.add(roleService.findApplicationRoleByImportId("default")) + applicationRoles.add(roleService.findApplicationRoleByImportId("admin")) + List processRoles = roleService.findAllProcessRolesByImportIds(["first", "second", "system", "identity", + "registration"] as Set) + Identity identity = importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Test")) + .lastname(new TextField("Integration")) + .password(new TextField("password")) + .username(new TextField(USER_EMAIL)) + .build(), processRoles + applicationRoles as List) + + Thread.sleep(2000) + + auth = new UsernamePasswordAuthenticationToken(identity.toSession(), "password") + auth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) + + objectWriter = objectMapper.writer().withDefaultPrettyPrinter() + } +} diff --git a/src/test/groovy/com/netgrif/application/engine/elastic/DataSearchRequestTest.groovy b/src/test/groovy/com/netgrif/application/engine/elastic/DataSearchRequestTest.groovy index 95fac47c82c..3b9d7b57155 100644 --- a/src/test/groovy/com/netgrif/application/engine/elastic/DataSearchRequestTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/elastic/DataSearchRequestTest.groovy @@ -2,9 +2,10 @@ package com.netgrif.application.engine.elastic import com.netgrif.application.engine.MockService import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authorization.service.interfaces.IUserService import com.netgrif.application.engine.elastic.domain.ElasticCase -import com.netgrif.application.engine.elastic.domain.ElasticCaseRepository +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticCaseRepository import com.netgrif.application.engine.elastic.domain.ElasticTask import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService import com.netgrif.application.engine.elastic.service.interfaces.IElasticIndexService @@ -18,12 +19,14 @@ import com.netgrif.application.engine.petrinet.domain.dataset.I18nField import com.netgrif.application.engine.petrinet.domain.dataset.TextField import com.netgrif.application.engine.petrinet.domain.dataset.UserFieldValue import com.netgrif.application.engine.petrinet.domain.dataset.UserListFieldValue +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.QTask import com.netgrif.application.engine.workflow.domain.Task +import com.netgrif.application.engine.workflow.domain.params.SetDataParams import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService @@ -51,9 +54,6 @@ import java.time.LocalTime @ExtendWith(SpringExtension.class) class DataSearchRequestTest { - public static final String PROCESS_TITLE = "Elastic data search request test" - public static final String PROCESS_INITIALS = "TST" - @Autowired private WebApplicationContext wac @@ -69,9 +69,6 @@ class DataSearchRequestTest { @Autowired private IWorkflowService workflowService - @Autowired - private IUserService userService - @Autowired private MockService mockService @@ -87,6 +84,12 @@ class DataSearchRequestTest { @Autowired private ITaskService taskService + @Autowired + private IIdentityService identityService + + @Autowired + private IUserService userService + @Autowired private IDataService dataService @@ -98,56 +101,55 @@ class DataSearchRequestTest { @BeforeEach void before() { testHelper.truncateDbs() -// template.deleteIndex(ElasticCase.class) + template.deleteIndex(ElasticCase.class) template.createIndex(ElasticCase.class) template.putMapping(ElasticCase.class) -// template.deleteIndex(ElasticTask.class) + template.deleteIndex(ElasticTask.class) template.createIndex(ElasticTask.class) template.putMapping(ElasticTask.class) repository.deleteAll() - def net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null - - def users = userService.findAll(true) - assert users.size() >= 2 - def testUser1 = users[0] - def testUser2 = users[1] - // saving authorities / roles crashes the workflowService (on case save) - testUser1.processRoles = [] - testUser1.authorities = [] - testUser2.processRoles = [] - testUser2.authorities = [] - - LocalDate date = LocalDate.of(2020, 7, 25); - Case _case = importHelper.createCase("correct", net.getNet()) + def net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/all_data.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + assert net.getProcess() != null + + def actors = userService.findAll() + assert actors.size() >= 2 + def testActor1 = actors[0] + def testActor2 = actors[1] + + LocalDate date = LocalDate.of(2020, 7, 25) + TestHelper.login(superCreator.superIdentity) + Case _case = importHelper.createCase("correct", net.getProcess()) _case.dataSet.get("number").rawValue = 7.0 as Double _case.dataSet.get("boolean").rawValue = true _case.dataSet.get("text").rawValue = "hello world" as String - _case.dataSet.get("user").rawValue = new UserFieldValue(testUser1.stringId, testUser1.name, testUser1.surname, testUser1.email) + _case.dataSet.get("user").rawValue = new UserFieldValue(testActor1.stringId, testActor1.firstname, + testActor1.lastname, testActor1.email) _case.dataSet.get("date").rawValue = date _case.dataSet.get("datetime").rawValue = date.atTime(13, 37) - _case.dataSet.get("enumeration").rawValue = (_case.petriNet.dataSet.get("enumeration") as ChoiceField).choices.find({ it.defaultValue == "Alice" }) - _case.dataSet.get("multichoice").rawValue = (_case.petriNet.dataSet.get("multichoice") as ChoiceField).choices.findAll({ it.defaultValue == "Alice" || it.defaultValue == "Bob" }).toSet() + _case.dataSet.get("enumeration").rawValue = (_case.process.dataSet.get("enumeration") as ChoiceField).choices.find({ it.defaultValue == "Alice" }) + _case.dataSet.get("multichoice").rawValue = (_case.process.dataSet.get("multichoice") as ChoiceField).choices.findAll({ it.defaultValue == "Alice" || it.defaultValue == "Bob" }).toSet() _case.dataSet.get("enumeration_map").rawValue = "alice" _case.dataSet.get("multichoice_map").rawValue = ["alice", "bob"].toSet() _case.dataSet.get("file").rawValue = FileFieldValue.fromString("singlefile.txt") _case.dataSet.get("fileList").rawValue = FileListFieldValue.fromString("multifile1.txt,multifile2.pdf") - _case.dataSet.get("userList").rawValue = new UserListFieldValue([dataService.makeUserFieldValue(testUser1.stringId), dataService.makeUserFieldValue(testUser2.stringId)]) + _case.dataSet.get("userList").rawValue = new UserListFieldValue([dataService.makeUserFieldValue(testActor1.stringId), dataService.makeUserFieldValue(testActor2.stringId)]) (_case.dataSet.get("i18n_text") as I18nField).rawValue.defaultValue = "Modified i18n text value" (_case.dataSet.get("i18n_divider") as I18nField).rawValue.defaultValue = "Modified i18n divider value" workflowService.save(_case) - Task actionTrigger = taskService.searchOne(QTask.task.caseId.eq(_case.stringId).and(QTask.task.transitionId.eq("2"))); + Task actionTrigger = taskService.searchOne(QTask.task.caseId.eq(_case.stringId) & QTask.task.transitionId.eq("t4")) assert actionTrigger != null - dataService.setData(actionTrigger, new DataSet([ + dataService.setData(new SetDataParams(actionTrigger, new DataSet([ "testActionTrigger": new TextField(rawValue: "random value") - ] as Map>), superCreator.getSuperUser()) + ] as Map>), superCreator.getLoggedSuper().activeActorId)) 10.times { - _case = importHelper.createCase("wrong${it}", net.getNet()) +// todo: release/8.0.0 created case already contains modified values -> problem with field cloning + _case = importHelper.createCase("wrong${it}", net.getProcess()) workflowService.save(_case) } @@ -158,10 +160,10 @@ class DataSearchRequestTest { new AbstractMap.SimpleEntry("boolean.booleanValue" as String, "true" as String), new AbstractMap.SimpleEntry("text" as String, "hello world" as String), new AbstractMap.SimpleEntry("text.textValue.keyword" as String, "hello world" as String), - new AbstractMap.SimpleEntry("user" as String, "${testUser1.fullName} ${testUser1.email}" as String), - new AbstractMap.SimpleEntry("user.emailValue.keyword" as String, "${testUser1.email}" as String), - new AbstractMap.SimpleEntry("user.fullNameValue.keyword" as String, "${testUser1.fullName}" as String), - new AbstractMap.SimpleEntry("user.userIdValue" as String, "${testUser1.getId()}" as String), + new AbstractMap.SimpleEntry("user" as String, "${testActor1.fullName} ${testActor1.email}" as String), + new AbstractMap.SimpleEntry("user.emailValue.keyword" as String, "${testActor1.email}" as String), + new AbstractMap.SimpleEntry("user.fullNameValue.keyword" as String, "${testActor1.fullName}" as String), + new AbstractMap.SimpleEntry("user.userIdValue" as String, "${testActor1.stringId}" as String), new AbstractMap.SimpleEntry("date.timestampValue" as String, "${Timestamp.valueOf(LocalDateTime.of(date, LocalTime.NOON)).getTime()}" as String), new AbstractMap.SimpleEntry("datetime.timestampValue" as String, "${Timestamp.valueOf(date.atTime(13, 37)).getTime()}" as String), new AbstractMap.SimpleEntry("enumeration" as String, "Alice" as String), @@ -200,14 +202,14 @@ class DataSearchRequestTest { new AbstractMap.SimpleEntry("fileList.fileNameValue.keyword" as String, "multifile2" as String), new AbstractMap.SimpleEntry("fileList.fileExtensionValue.keyword" as String, "txt" as String), new AbstractMap.SimpleEntry("fileList.fileExtensionValue.keyword" as String, "pdf" as String), - new AbstractMap.SimpleEntry("userList" as String, "${testUser1.fullName} ${testUser1.email}" as String), - new AbstractMap.SimpleEntry("userList" as String, "${testUser2.fullName} ${testUser2.email}" as String), - new AbstractMap.SimpleEntry("userList.emailValue.keyword" as String, "${testUser1.email}" as String), - new AbstractMap.SimpleEntry("userList.emailValue.keyword" as String, "${testUser2.email}" as String), - new AbstractMap.SimpleEntry("userList.fullNameValue.keyword" as String, "${testUser1.fullName}" as String), - new AbstractMap.SimpleEntry("userList.fullNameValue.keyword" as String, "${testUser2.fullName}" as String), - new AbstractMap.SimpleEntry("userList.userIdValue" as String, "${testUser1.getId()}" as String), - new AbstractMap.SimpleEntry("userList.userIdValue" as String, "${testUser2.getId()}" as String), + new AbstractMap.SimpleEntry("userList" as String, "${testActor1.fullName} ${testActor1.email}" as String), + new AbstractMap.SimpleEntry("userList" as String, "${testActor2.fullName} ${testActor2.email}" as String), + new AbstractMap.SimpleEntry("userList.emailValue.keyword" as String, "${testActor1.email}" as String), + new AbstractMap.SimpleEntry("userList.emailValue.keyword" as String, "${testActor2.email}" as String), + new AbstractMap.SimpleEntry("userList.fullNameValue.keyword" as String, "${testActor1.fullName}" as String), + new AbstractMap.SimpleEntry("userList.fullNameValue.keyword" as String, "${testActor2.fullName}" as String), + new AbstractMap.SimpleEntry("userList.userIdValue" as String, "${testActor1.stringId}" as String), + new AbstractMap.SimpleEntry("userList.userIdValue" as String, "${testActor2.stringId}" as String), new AbstractMap.SimpleEntry("enumeration_map_changed" as String, "Eve" as String), new AbstractMap.SimpleEntry("enumeration_map_changed" as String, "Eva" as String), new AbstractMap.SimpleEntry("enumeration_map_changed.textValue.keyword" as String, "Eve" as String), @@ -237,7 +239,8 @@ class DataSearchRequestTest { log.info(String.format("Testing %s == %s", testCase.getKey(), testCase.getValue())) - Page result = searchService.search([request] as List, mockService.mockLoggedUser(), PageRequest.of(0, 100), null, false) + Page result = searchService.search([request] as List, superCreator.loggedSuper.activeActorId, + PageRequest.of(0, 100), null, false) assert result assert result.size() == 1 } diff --git a/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy b/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy index 719f75665cc..550c2fb77a9 100644 --- a/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy @@ -1,14 +1,15 @@ package com.netgrif.application.engine.elastic -import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.ApplicationEngine -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.elastic.domain.ElasticCaseRepository +import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticCaseRepository import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationField -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator @@ -17,7 +18,6 @@ import groovy.json.JsonOutput import groovy.json.JsonSlurper import groovy.util.logging.Slf4j import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired @@ -86,6 +86,9 @@ class ElasticSearchTest { @Autowired private SuperCreator superCreator + @Autowired + private IRoleService roleService + @Autowired private TestHelper testHelper @@ -102,25 +105,29 @@ class ElasticSearchTest { .apply(springSecurity()) .build() - def net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet() - def net2 = petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet() + def net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/all_data.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() + def net2 = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() + assert net assert net2 netId = net.getStringId() netId2 = net2.getStringId() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSW, state: UserState.ACTIVE), - [auths.get("user")] as Authority[], - [net.roles.values().find { it.importId == "process_role" }] as ProcessRole[]) - auth = new UsernamePasswordAuthenticationToken(USER_EMAIL, USER_PASSW) - auth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())); + Identity identity = importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Test")) + .lastname(new TextField("Integration")) + .username(new TextField(USER_EMAIL)) + .password(new TextField(USER_PASSW)) + .build(), List.of(roleService.findProcessRoleByImportId("process_role"))) + auth = new UsernamePasswordAuthenticationToken(identity.toSession(), USER_PASSW) + auth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) CASE_NUMBER.times { def _case = importHelper.createCaseAsSuper("$it" as String, it % 2 == 0 ? net : net2) _case.dataSet.get("number").rawValue = it * 100.0 as Double - _case.dataSet.get("enumeration").rawValue = (_case.petriNet.dataSet.get("enumeration") as EnumerationField).choices[it % 3] + _case.dataSet.get("enumeration").rawValue = (_case.process.dataSet.get("enumeration") as EnumerationField).choices[it % 3] workflowService.save(_case) } @@ -136,7 +143,7 @@ class ElasticSearchTest { "searchByAuthorIdAndIdentifier" : [ "json": JsonOutput.toJson([ "author": [ - "id": superCreator.superUser.stringId + "id": superCreator.superIdentity.mainActorId ], "process": [ "identifier": "all_data" @@ -147,27 +154,28 @@ class ElasticSearchTest { "searchByAuthorId" : [ "json": JsonOutput.toJson([ "author": [ - "id": superCreator.superUser.stringId - ] - ]), - "size": CASE_NUMBER + SYSTEM_CASE_NUMBER - ], - "searchByAuthorName" : [ - "json": JsonOutput.toJson([ - "author": [ - "name": superCreator.superUser.fullName - ] - ]), - "size": CASE_NUMBER + SYSTEM_CASE_NUMBER - ], - "searchByAuthorEmail" : [ - "json": JsonOutput.toJson([ - "author": [ - "email": superCreator.superUser.email + "id": superCreator.superIdentity.mainActorId ] ]), - "size": CASE_NUMBER + SYSTEM_CASE_NUMBER + "size": CASE_NUMBER ], + // todo: release/8.0.0 author email,name is not indexed +// "searchByAuthorName" : [ +// "json": JsonOutput.toJson([ +// "author": [ +// "name": superCreator.superIdentity.fullName +// ] +// ]), +// "size": CASE_NUMBER + SYSTEM_CASE_NUMBER +// ], +// "searchByAuthorEmail" : [ +// "json": JsonOutput.toJson([ +// "author": [ +// "email": superCreator.superIdentity.username +// ] +// ]), +// "size": CASE_NUMBER + SYSTEM_CASE_NUMBER +// ], "searchByEnumeration" : [ "json": JsonOutput.toJson([ "data": [ diff --git a/src/test/groovy/com/netgrif/application/engine/elastic/ElasticTaskTest.groovy b/src/test/groovy/com/netgrif/application/engine/elastic/ElasticTaskTest.groovy index 06ee0a5ec05..181e84f1ffa 100644 --- a/src/test/groovy/com/netgrif/application/engine/elastic/ElasticTaskTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/elastic/ElasticTaskTest.groovy @@ -3,10 +3,11 @@ package com.netgrif.application.engine.elastic import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.ApplicationEngine import com.netgrif.application.engine.elastic.domain.ElasticTask -import com.netgrif.application.engine.elastic.domain.ElasticTaskRepository +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticTaskRepository import com.netgrif.application.engine.elastic.service.ReindexingTask import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator @@ -16,10 +17,8 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired -import org.springframework.beans.factory.annotation.Value import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc import org.springframework.boot.test.context.SpringBootTest -import org.springframework.core.io.Resource import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension @@ -68,9 +67,6 @@ class ElasticTaskTest { @Autowired protected IElasticTaskService elasticTaskService - @Value("classpath:task_reindex_test.xml") - private Resource netResource - @BeforeEach void before() { testHelper.truncateDbs() @@ -78,10 +74,12 @@ class ElasticTaskTest { @Test void taskReindexTest() { - def optional = petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert optional.getNet() != null + def optional = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/all_data.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + assert optional.getProcess() != null - def net = optional.getNet() + def net = optional.getProcess() + TestHelper.login(superCreator.superIdentity) 10.times { helper.createCase("Case $it", net) } @@ -100,7 +98,7 @@ class ElasticTaskTest { ElasticTask result = resultFuture.get() assert result != null - assert result.getTitle().equals("Test") + assert result.getTitle() == "Test" ElasticTask resultFromDB = elasticTaskRepository.findByTaskId("TestTask") assert resultFromDB.getTitle() == "Test" @@ -111,7 +109,7 @@ class ElasticTaskTest { ElasticTask result2 = resultFuture2.get() assert result2 != null - assert result2.getTitle().equals("Test2") + assert result2.getTitle() == "Test2" task.setTitle("Test3") @@ -119,7 +117,7 @@ class ElasticTaskTest { ElasticTask result3 = resultFuture3.get() assert result3 != null - assert result3.getTitle().equals("Test3") + assert result3.getTitle() == "Test3" } @Test @@ -165,7 +163,7 @@ class ElasticTaskTest { Future resultFuture = elasticTaskService.scheduleTaskIndexing(taskParallel) ElasticTask result = resultFuture.get() assert result != null - assert result.getTitle().equals("START" + index) + assert result.getTitle() == "START" + index } catch (Exception e) { e.printStackTrace() } finally { @@ -207,7 +205,7 @@ class ElasticTaskTest { Future resultFuture = elasticTaskService.scheduleTaskIndexing(taskParallel) ElasticTask result = resultFuture.get() assert result != null - assert result.getTitle().equals("START" + index) + assert result.getTitle() == "START" + index } catch (Exception e) { e.printStackTrace() } finally { @@ -223,7 +221,7 @@ class ElasticTaskTest { Future resultFuture = elasticTaskService.scheduleTaskIndexing(task) as CompletableFuture ElasticTask result = resultFuture.get() assert result != null - assert result.getTitle().equals(title) + assert result.getTitle() == title } @@ -249,7 +247,7 @@ class ElasticTaskTest { Future resultFuture = elasticTaskService.scheduleTaskIndexing(taskParallel) ElasticTask result = resultFuture.get() assert result != null - assert result.getTitle().equals("TestTask"+ index) + assert result.getTitle() == "TestTask" + index } catch (Exception e) { e.printStackTrace() } finally { @@ -273,7 +271,7 @@ class ElasticTaskTest { Future resultFuture = elasticTaskService.scheduleTaskIndexing(task) as CompletableFuture ElasticTask result = resultFuture.get() assert result != null - assert result.getTitle().equals(title) + assert result.getTitle() == title } diff --git a/src/test/groovy/com/netgrif/application/engine/elastic/ReindexTest.groovy b/src/test/groovy/com/netgrif/application/engine/elastic/ReindexTest.groovy index db93093eb26..fa0a3f73fcf 100644 --- a/src/test/groovy/com/netgrif/application/engine/elastic/ReindexTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/elastic/ReindexTest.groovy @@ -5,10 +5,12 @@ import com.netgrif.application.engine.elastic.service.ReindexingTask import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -50,14 +52,21 @@ class ReindexTest { @Test void reindexTest() { - ImportPetriNetEventOutcome net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null + ImportPetriNetEventOutcome net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/all_data.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + assert net.getProcess() != null int countTread = Thread.activeCount() List threads = [] List savedCase = [] + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net.getProcess()) + .title("Test") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() for (int i in 1..2000) { threads << Thread.start { - def useCase = workflowService.createCase(net.getNet().stringId, "Test", "color", superCreator.getLoggedSuper()).getCase() + TestHelper.login(superCreator.superIdentity) + def useCase = workflowService.createCase(createCaseParams).getCase() savedCase.add(useCase) } } @@ -69,7 +78,8 @@ class ReindexTest { threads = [] for (int i in 1..4000) { threads << Thread.start { - def useCase = workflowService.createCase(net.getNet().stringId, "Test", "color", superCreator.getLoggedSuper()).getCase() + TestHelper.login(superCreator.superIdentity) + def useCase = workflowService.createCase(createCaseParams).getCase() savedCase.add(useCase) } } @@ -85,7 +95,8 @@ class ReindexTest { savedCase.forEach(it -> { CaseSearchRequest request = new CaseSearchRequest() request.query = "stringId:\"" + it.getStringId() + "\"" - List result = elasticCaseService.search(Collections.singletonList(request), superCreator.getLoggedSuper(), PageRequest.of(0, 10), LocaleContextHolder.getLocale(), false).getContent() + List result = elasticCaseService.search(Collections.singletonList(request), superCreator.getLoggedSuper().activeActorId, + PageRequest.of(0, 10), LocaleContextHolder.getLocale(), false).getContent() assert result.size() == 1 }) } diff --git a/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy b/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy index b5296effb6b..f3de7a923fd 100644 --- a/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy @@ -1,81 +1,42 @@ package com.netgrif.application.engine.event +import com.netgrif.application.engine.EngineTest import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.LoggedUser -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.service.interfaces.IUserService import com.netgrif.application.engine.petrinet.domain.I18nString -import com.netgrif.application.engine.petrinet.domain.PetriNet -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService -import com.netgrif.application.engine.startup.ImportHelper +import com.netgrif.application.engine.petrinet.domain.Process +import com.netgrif.application.engine.authorization.domain.ProcessRole +import com.netgrif.application.engine.utils.UniqueKeyMapWrapper import com.netgrif.application.engine.workflow.domain.QTask -import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest -import org.springframework.http.MediaType -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.security.web.authentication.WebAuthenticationDetails import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension -import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.setup.MockMvcBuilders -import org.springframework.web.context.WebApplicationContext - -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication -import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @SpringBootTest -class GroovyShellFactoryTest { - - private static final String USER_EMAIL = "test@test.com" - private static final String USER_PASSW = "password" +class GroovyShellFactoryTest extends EngineTest { public static final String FILE_NAME = "groovy_shell_test.xml" - @Autowired - private ImportHelper importHelper - - @Autowired - private WebApplicationContext wac - - @Autowired - private TestHelper testHelper - - @Autowired - private ITaskService taskService - - @Autowired - private IProcessRoleService roleService - - @Autowired - private IUserService userService - - private PetriNet net - + private Process net + private UniqueKeyMapWrapper roles @BeforeEach + @Override void before() { - testHelper.truncateDbs() + super.before() def testNet = importHelper.createNet(FILE_NAME) assert testNet.isPresent() net = testNet.get() } - @Test void caseFieldsExpressionTest() { + TestHelper.login(superCreator.superIdentity) def _case = importHelper.createCase("case", net) assert _case.dataSet.get("newVariable_1").rawValue == "value" } @@ -84,25 +45,26 @@ class GroovyShellFactoryTest { void roleActionsTest() { userService.metaClass.groovyShellTestMethod = { String string, I18nString i18nString -> println("groovyShellTestMethod") } - def user = userService.findByEmail(userService.getSystem().getEmail(), false) - def processRoleCount = user.processRoles.size() - def roles = roleService.findAll(net.getStringId()) - assert roles.size() == 1 - roleService.assignRolesToUser( - user.getStringId(), - new HashSet(roles.collect { it.stringId } + user.processRoles.collect { it.stringId }), - new LoggedUser("", "a", "", []) - ) - user = userService.findByEmail(userService.getSystem().getEmail(), false) - assert user.processRoles.size() == processRoleCount + 1 + def userOpt = userService.findById(superCreator.superIdentity.mainActorId) + assert userOpt.isPresent() +// def roleCount = actor.roles.size() + def roles = roleService.findAll() + def roleId = "newRole_1" + def role = roles.find {it.importId == roleId} + assert role != null + roleService.assignRolesToActor(userOpt.get().stringId, [role.stringId] as Set) + // todo: release/8.0.0 some assertions to check shell? +// actor = userService.findByEmail(userService.getSystem().getEmail()) +// assert actor.roles.size() == roleCount + 1 } @Test void fieldActionsTest() { + TestHelper.login(superCreator.superIdentity) def _case = importHelper.createCase("case", net) importHelper.assignTaskToSuper("task", _case.getStringId()) - def task = taskService.searchOne(QTask.task.transitionId.eq("t1")) + def task = taskService.searchOne(QTask.task.transitionId.eq("t1") & QTask.task.caseId.eq(_case.stringId)) assert task != null - assert task.getUserId() != null + assert task.assigneeId != null } } diff --git a/src/test/groovy/com/netgrif/application/engine/export/service/ExportServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/export/service/ExportServiceTest.groovy index eebfcd33e69..adc54b926f8 100644 --- a/src/test/groovy/com/netgrif/application/engine/export/service/ExportServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/export/service/ExportServiceTest.groovy @@ -1,20 +1,23 @@ package com.netgrif.application.engine.export.service import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService + import com.netgrif.application.engine.elastic.web.requestbodies.ElasticTaskSearchRequest import com.netgrif.application.engine.export.service.interfaces.IExportService -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionDelegate import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper +import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.QTask import com.netgrif.application.engine.workflow.domain.Task +import com.netgrif.application.engine.workflow.domain.params.TaskParams import com.netgrif.application.engine.workflow.domain.repositories.TaskRepository import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService +import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.PetriNet import groovy.transform.CompileStatic import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled @@ -24,7 +27,7 @@ import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.ActiveProfiles -import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.context.junit.jupiter.SpringExtension @SpringBootTest @@ -45,9 +48,6 @@ class ExportServiceTest { @Autowired private ITaskService taskService - @Autowired - private IUserService userService - @Autowired private TestHelper testHelper @@ -60,15 +60,19 @@ class ExportServiceTest { @Autowired private IExportService exportService - PetriNet testNet + @Autowired + private SuperCreator superCreator + + Process testNet Case mainCase @BeforeEach void before() { testHelper.truncateDbs() - Optional optionalTestNet = importHelper.createNet("NAE-1290_Export_actions.xml", VersionType.MAJOR) + Optional optionalTestNet = importHelper.createNet("NAE-1290_Export_actions.xml", VersionType.MAJOR) assert optionalTestNet.isPresent() testNet = optionalTestNet.get() + TestHelper.login(superCreator.superIdentity) mainCase = importHelper.createCase("export test main", testNet) 9.times { importHelper.createCase("export test", testNet) @@ -79,14 +83,14 @@ class ExportServiceTest { @Order(2) void testCaseMongoExport() { String exportTask = mainCase.getTaskStringId("t1") - taskService.assignTask(userService.findByEmail("super@netgrif.com").transformToLoggedUser(), exportTask) + taskService.assignTask(new TaskParams(superCreator.getLoggedSuper().activeActorId, exportTask)) File csvFile = new File("src/test/resources/csv/case_mongo_export.csv") assert csvFile.readLines().size() == 11 String[] headerSplit = csvFile.readLines()[0].split(",") assert (headerSplit.contains("immediate_multichoice") && headerSplit.contains("immediate_number") && !headerSplit.contains("text")) - taskService.cancelTask(userService.getLoggedOrSystem().transformToLoggedUser(), exportTask) + taskService.cancelTask(new TaskParams(superCreator.getLoggedSuper().activeActorId, exportTask)) } @Test @@ -94,21 +98,21 @@ class ExportServiceTest { void testCaseElasticExport() { Thread.sleep(5000) //Elastic wait String exportTask = mainCase.getTaskStringId("t2") - taskService.assignTask(userService.findByEmail("super@netgrif.com").transformToLoggedUser(), exportTask) + taskService.assignTask(new TaskParams(superCreator.getLoggedSuper().activeActorId, exportTask)) File csvFile = new File("src/test/resources/csv/case_elastic_export.csv") assert csvFile.readLines().size() == 11 String[] headerSplit = csvFile.readLines()[0].split(",") assert (headerSplit.contains("text") && !headerSplit.contains("immediate_multichoice") && !headerSplit.contains("immediate_number")) - taskService.cancelTask(userService.getLoggedOrSystem().transformToLoggedUser(), exportTask) + taskService.cancelTask(new TaskParams(superCreator.getLoggedSuper().activeActorId, exportTask)) } @Test @Order(4) void testTaskMongoExport() { String exportTask = mainCase.getTaskStringId("t3") - taskService.assignTask(userService.findByEmail("super@netgrif.com").transformToLoggedUser(), exportTask) + taskService.assignTask(new TaskParams(superCreator.getLoggedSuper().activeActorId, exportTask)) File csvFile = new File("src/test/resources/csv/task_mongo_export.csv") assert csvFile.readLines().size() == 11 String[] headerSplit = csvFile.readLines()[0].split(",") @@ -116,7 +120,7 @@ class ExportServiceTest { && headerSplit.contains("immediate_number") && headerSplit.contains("text") && !headerSplit.contains("no_export")) - taskService.cancelTask(userService.getLoggedOrSystem().transformToLoggedUser(), exportTask) + taskService.cancelTask(new TaskParams(superCreator.getLoggedSuper().activeActorId, exportTask)) } @Test @@ -125,31 +129,32 @@ class ExportServiceTest { void testTaskElasticExport() { Thread.sleep(10000) //Elastic wait String exportTask = mainCase.getTaskStringId("t4") - taskService.assignTask(userService.findByEmail("super@netgrif.com").transformToLoggedUser(), exportTask) + taskService.assignTask(new TaskParams(superCreator.getLoggedSuper().activeActorId, exportTask)) Thread.sleep(20000) //Elastic wait def processId = petriNetService.getNewestVersionByIdentifier("export_test").stringId def taskRequest = new ElasticTaskSearchRequest() - taskRequest.process = [new com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.PetriNet(processId)] as List + taskRequest.process = [new PetriNet(processId)] as List taskRequest.transitionId = ["t4"] as List - actionDelegate.exportTasksToFile([taskRequest],"src/test/resources/csv/task_elastic_export.csv",null, userService.findByEmail("super@netgrif.com").transformToLoggedUser()) + actionDelegate.exportTasksToFile([taskRequest],"src/test/resources/csv/task_elastic_export.csv",null, + superCreator.getLoggedSuper()) File csvFile = new File("src/test/resources/csv/task_elastic_export.csv") - int count = ((taskRepository.count(QTask.task.processId.eq(processId).and(QTask.task.transitionId.eq("t4"))) as int) + 1) + int count = ((taskRepository.count(QTask.task.processId.eq(processId) & QTask.task.transitionId.eq("t4")) as int) + 1) assert csvFile.readLines().size() == count String[] headerSplit = csvFile.readLines()[0].split(",") assert (headerSplit.contains("immediate_multichoice") && headerSplit.contains("immediate_number") && !headerSplit.contains("text") && !headerSplit.contains("no_export")) - taskService.cancelTask(userService.findByEmail("super@netgrif.com").transformToLoggedUser(), exportTask) + taskService.cancelTask(new TaskParams(superCreator.getLoggedSuper().activeActorId, exportTask)) } @Test void buildDefaultCsvTaskHeaderTest(){ def processId = petriNetService.getNewestVersionByIdentifier("export_test").stringId String exportTask = mainCase.getTaskStringId("t4") - taskService.assignTask(userService.findByEmail("super@netgrif.com").transformToLoggedUser(), exportTask) - List task = taskRepository.findAll(QTask.task.processId.eq(processId).and(QTask.task.transitionId.eq("t4"))) as List + taskService.assignTask(new TaskParams(superCreator.getLoggedSuper().activeActorId, exportTask)) + List task = taskRepository.findAll(QTask.task.processId.eq(processId) & QTask.task.transitionId.eq("t4")) as List Set header = exportService.buildDefaultCsvTaskHeader(task) assert header != null // TODO: release/8.0.0 empty header diff --git a/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy b/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy index bb9716a1deb..78c411b928c 100644 --- a/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy @@ -1,23 +1,24 @@ package com.netgrif.application.engine.filters import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField import com.netgrif.application.engine.petrinet.domain.dataset.Field import com.netgrif.application.engine.petrinet.domain.dataset.FileFieldValue import com.netgrif.application.engine.petrinet.domain.dataset.FilterField import com.netgrif.application.engine.petrinet.domain.dataset.TaskField import com.netgrif.application.engine.petrinet.domain.dataset.TextField -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole import com.netgrif.application.engine.startup.DefaultFiltersRunner import com.netgrif.application.engine.startup.FilterRunner import com.netgrif.application.engine.startup.ImportHelper +import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.* import com.netgrif.application.engine.workflow.domain.filter.FilterImportExportList -import com.netgrif.application.engine.workflow.service.UserFilterSearchService +import com.netgrif.application.engine.workflow.domain.params.SetDataParams +import com.netgrif.application.engine.workflow.domain.params.TaskParams +import com.netgrif.application.engine.workflow.service.ActorFilterSearchService import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.IFilterImportExportService import com.netgrif.application.engine.workflow.service.interfaces.ITaskService @@ -71,34 +72,37 @@ class FilterImportExportTest { private static final String FILTER_FIELD = "filter" @Autowired - IFilterImportExportService importExportService + private IFilterImportExportService importExportService @Autowired - FilterRunner filterRunner + private FilterRunner filterRunner @Autowired - TestHelper testHelper + private TestHelper testHelper @Autowired - IWorkflowService workflowService + private IWorkflowService workflowService @Autowired - ImportHelper importHelper + private ImportHelper importHelper @Autowired - DefaultFiltersRunner defaultFiltersRunner + private DefaultFiltersRunner defaultFiltersRunner @Autowired - UserFilterSearchService userFilterSearchService + private ActorFilterSearchService userFilterSearchService @Autowired - ITaskService taskService + private ITaskService taskService @Autowired private IDataService dataService + @Autowired + private SuperCreator superCreator + private Authentication userAuth - private User dummyUser + private Identity dummyIdentity private Case importCase private Case exportCase @@ -106,23 +110,25 @@ class FilterImportExportTest { void setup() { this.testHelper.truncateDbs() this.defaultFiltersRunner.run() + TestHelper.login(superCreator.superIdentity) createTestFilter() - dummyUser = createDummyUser() - userAuth = new UsernamePasswordAuthenticationToken(dummyUser.transformToLoggedUser(), DUMMY_USER_PASSWORD) + dummyIdentity = createDummyIdentity() + userAuth = new UsernamePasswordAuthenticationToken(createDummyIdentity().toSession(), DUMMY_USER_PASSWORD) SecurityContextHolder.getContext().setAuthentication(userAuth) - Optional importNet = this.filterRunner.createImportFiltersNet() - Optional exportNet = this.filterRunner.createExportFiltersNet() + Optional importNet = this.filterRunner.createImportFiltersNet() + Optional exportNet = this.filterRunner.createExportFiltersNet() assert importNet.isPresent() assert exportNet.isPresent() importCase = this.workflowService.searchOne( - QCase.case$.processIdentifier.eq(IMPORT_NET_IDENTIFIER).and(QCase.case$.author.email.eq(DUMMY_USER_MAIL)) + QCase.case$.processIdentifier.eq(IMPORT_NET_IDENTIFIER) & QCase.case$.authorId.eq(dummyIdentity.mainActorId) ) + assert importCase != null // todo: release/8.0.0 fails because identityService doesnt create cases + exportCase = this.workflowService.searchOne( - QCase.case$.processIdentifier.eq(EXPORT_NET_IDENTIFIER).and(QCase.case$.author.email.eq(DUMMY_USER_MAIL)) + QCase.case$.processIdentifier.eq(EXPORT_NET_IDENTIFIER) & QCase.case$.authorId.eq(dummyIdentity.mainActorId) ) - assert importCase != null assert exportCase != null } @@ -148,16 +154,16 @@ class FilterImportExportTest { validateFilterXML(new FileInputStream(exportedFiltersField.getPath())) importedTasksIds.forEach({ taskId -> Task filterTask = this.taskService.findOne(taskId) - this.dataService.setData(filterTask, new DataSet([ + this.dataService.setData(new SetDataParams(filterTask, new DataSet([ (VISIBILITY_FIELD): new EnumerationMapField(rawValue: FILTER_VISIBILITY_PRIVATE), (NEW_TITLE_FIELD) : new TextField(rawValue: this.workflowService.findOne(filterTask.caseId).title + " new") - ] as Map>)) + ] as Map>), dummyIdentity.toSession().activeActorId)) }) - Task importTask = this.taskService.searchOne(QTask.task.caseId.eq(importCase.stringId).and(QTask.task.transitionId.eq("importFilter"))) - this.dataService.setData(importTask, new DataSet([ + Task importTask = this.taskService.searchOne(QTask.task.caseId.eq(importCase.stringId) & QTask.task.transitionId.eq("importFilter")) + this.dataService.setData(new SetDataParams(importTask, new DataSet([ (IMPORTED_FILTERS_FIELD): new TaskField(rawValue: importedTasksIds) - ] as Map>)) - this.taskService.finishTask(importTask, dummyUser) + ] as Map>), dummyIdentity.toSession().activeActorId)) + this.taskService.finishTask(new TaskParams(importTask, dummyIdentity.toSession().activeActorId)) Thread.sleep(1000) filterCases = this.userFilterSearchService.autocompleteFindFilters("") List filterCasesNames = filterCases.stream().map({ filterCase -> filterCase.title }).collect(Collectors.toList()) @@ -295,11 +301,13 @@ class FilterImportExportTest { }) } - private User createDummyUser() { - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - return importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: DUMMY_USER_PASSWORD, state: UserState.ACTIVE), - [auths.get("user")] as Authority[], - [] as ProcessRole[]) + private Identity createDummyIdentity() { + return importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Dummy")) + .lastname(new TextField("Identity")) + .username(new TextField(DUMMY_USER_MAIL)) + .password(new TextField(DUMMY_USER_PASSWORD)) + .build(), new ArrayList<>()) } private static void validateFilterXML(InputStream xml) throws IllegalFilterFileException { diff --git a/src/test/groovy/com/netgrif/application/engine/history/HistoryServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/history/HistoryServiceTest.groovy index 16943c2c091..e38d7270f92 100644 --- a/src/test/groovy/com/netgrif/application/engine/history/HistoryServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/history/HistoryServiceTest.groovy @@ -1,16 +1,19 @@ package com.netgrif.application.engine.history import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService + import com.netgrif.application.engine.history.service.IHistoryService -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.dataset.NumberField +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams +import com.netgrif.application.engine.workflow.domain.params.SetDataParams +import com.netgrif.application.engine.workflow.domain.params.TaskParams import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService @@ -49,51 +52,65 @@ class HistoryServiceTest { @Autowired private SuperCreator superCreator - @Autowired - private IUserService userService - - private PetriNet net + private Process net @BeforeEach void init() { testHelper.truncateDbs() - ImportPetriNetEventOutcome net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null - this.net = net.getNet() + ImportPetriNetEventOutcome net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/all_data.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) + assert net.getProcess() != null + this.net = net.getProcess() } @Test void findAllAssignTaskEventLogsByCaseIdTest() { - Case caze = workflowService.createCase(net.getStringId(), "Test assign", "", superCreator.getLoggedSuper()).getCase() + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Test assign") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case caze = workflowService.createCase(createCaseParams).getCase() int count = historyService.findAllAssignTaskEventLogsByCaseId(caze.getStringId()).size() assert count == 0 - String task = caze.tasks.values().find { it.transitionId == "1" }.taskStringId - taskService.assignTask(superCreator.getLoggedSuper(), task) + String task = caze.getTaskStringId("t1") + taskService.assignTask(new TaskParams(task, superCreator.getLoggedSuper().activeActorId)) Thread.sleep(1000) // HistoryService::save is @Async assert historyService.findAllAssignTaskEventLogsByCaseId(caze.getStringId()).size() == count + 2 // 2 PRE POST } @Test void findAllFinishTaskEventLogsByCaseId() { - Case caze = workflowService.createCase(net.getStringId(), "Test finish", "", superCreator.getLoggedSuper()).getCase() + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Test finish") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case caze = workflowService.createCase(createCaseParams).getCase() int count = historyService.findAllFinishTaskEventLogsByCaseId(caze.getStringId()).size() assert count == 0 - String task = caze.tasks.values().find { it.transitionId == "1" }.taskStringId - taskService.assignTask(superCreator.getLoggedSuper(), task) + String task = caze.getTaskStringId("t1") + taskService.assignTask(new TaskParams(task, superCreator.getLoggedSuper().activeActorId)) assert historyService.findAllFinishTaskEventLogsByCaseId(caze.getStringId()).size() == count - taskService.finishTask(superCreator.getLoggedSuper(), task) + taskService.finishTask(new TaskParams(task, superCreator.getLoggedSuper().activeActorId)) Thread.sleep(1000) // HistoryService::save is @Async assert historyService.findAllFinishTaskEventLogsByCaseId(caze.getStringId()).size() == count + 2 // 2 PRE POST } @Test void findAllSetDataEventLogsByCaseId() { - Case caze = workflowService.createCase(net.getStringId(), "Test set data", "", superCreator.getLoggedSuper()).getCase() + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Test set data") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case caze = workflowService.createCase(createCaseParams).getCase() int count = historyService.findAllSetDataEventLogsByCaseId(caze.getStringId()).size() assert count == 0 - String task = caze.tasks.values().find { it.transitionId == "1" }.taskStringId - dataService.setData(task, DataSet.of("number", new NumberField(rawValue: 110101116103114105102)), userService.loggedOrSystem) + String task = caze.getTaskStringId("t1") + dataService.setData(new SetDataParams(task, DataSet.of("number", new NumberField(rawValue: 110101116103114105102)), + superCreator.getLoggedSuper().activeActorId)) Thread.sleep(1000) // HistoryService::save is @Async assert historyService.findAllSetDataEventLogsByCaseId(caze.getStringId()).size() == count + 3 // 3 PRE EXECUTION POST } diff --git a/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy deleted file mode 100644 index e0578a3d8a0..00000000000 --- a/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy +++ /dev/null @@ -1,337 +0,0 @@ -package com.netgrif.application.engine.impersonation - -import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.IUser -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService -import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationAuthorizationService -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService -import com.netgrif.application.engine.petrinet.domain.I18nString -import com.netgrif.application.engine.petrinet.domain.PetriNet -import com.netgrif.application.engine.petrinet.domain.dataset.MultichoiceMapField -import com.netgrif.application.engine.petrinet.domain.dataset.UserFieldValue -import com.netgrif.application.engine.petrinet.domain.dataset.UserListFieldValue -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.ImpersonationRunner -import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.Task -import com.netgrif.application.engine.workflow.service.interfaces.* -import com.netgrif.application.engine.workflow.web.requestbodies.TaskSearchRequest -import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.TaskSearchCaseRequest -import groovy.json.JsonSlurper -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.context.i18n.LocaleContextHolder -import org.springframework.data.domain.PageRequest -import org.springframework.http.MediaType -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.security.core.Authentication -import org.springframework.security.core.context.SecurityContextHolder -import org.springframework.security.web.authentication.WebAuthenticationDetails -import org.springframework.session.web.http.SessionRepositoryFilter -import org.springframework.test.context.ActiveProfiles -import org.springframework.test.context.junit.jupiter.SpringExtension -import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.setup.MockMvcBuilders -import org.springframework.web.context.WebApplicationContext - -import java.time.LocalDateTime - -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic -import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status - -@SpringBootTest -@ActiveProfiles(["test"]) -@ExtendWith(SpringExtension.class) -class ImpersonationServiceTest { - - public static final String X_AUTH_TOKEN = "x-auth-token" - - @Autowired - private TestHelper testHelper - - @Autowired - private ImportHelper helper - - @Autowired - private IUserService userService - - @Autowired - private IElasticCaseService elasticCaseService - - @Autowired - private IWorkflowService workflowService - - @Autowired - private IDataService dataService - - @Autowired - private ITaskService taskService - - @Autowired - private IPetriNetService petriNetService - - @Autowired - private IAuthorityService authorityService - - @Autowired - private IImpersonationService impersonationService - - @Autowired - private IImpersonationAuthorizationService impersonationAuthorizationService - - @Autowired - private ITaskAuthorizationService taskAuthorizationService - - @Autowired - private IWorkflowAuthorizationService workflowAuthorizationService - - @Autowired - private WebApplicationContext wac - - MockMvc mvc - - Authentication auth1 - Authentication auth2 - Authentication adminUserAuth - - IUser user1 - IUser user2 - IUser adminUser - - PetriNet testNet - - @BeforeEach - void before() { - testHelper.truncateDbs() - - SessionRepositoryFilter filter = wac.getBean(SessionRepositoryFilter.class); - mvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(filter).apply(springSecurity()).build() - - testNet = helper.createNet("impersonation_test.xml").get() - def authority = authorityService.getOrCreate(Authority.user) - def authorityAnon = authorityService.getOrCreate(Authority.anonymous) - def authorityAdmin = authorityService.getOrCreate(Authority.admin) - - user1 = helper.createUser(new User(name: "Test", surname: "User", email: "test@netgrif.com", password: "password", state: UserState.ACTIVE), - [authority] as Authority[], - [] as ProcessRole[]) - - auth1 = new UsernamePasswordAuthenticationToken(user1.transformToLoggedUser(), (user1 as User).password, user1.authorities) - auth1.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) - - user2 = helper.createUser(new User(name: "Test", surname: "User2", email: "test2@netgrif.com", password: "password", state: UserState.ACTIVE), - [authority, authorityAnon] as Authority[], - testNet.roles.values() as ProcessRole[]) - - auth2 = new UsernamePasswordAuthenticationToken(user2.transformToLoggedUser(), (user2 as User).password, user2.authorities) - auth2.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) - - adminUser = helper.createUser(new User(name: "Admin", surname: "User", email: "admin@netgrif.com", password: "password", state: UserState.ACTIVE), - [authority, authorityAdmin] as Authority[], - testNet.roles.values() as ProcessRole[]) - - adminUserAuth = new UsernamePasswordAuthenticationToken(adminUser.transformToLoggedUser(), (adminUser as User).password, adminUser.authorities) - adminUserAuth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) - } - - @Test - void testImpersonationAdmin() { - SecurityContextHolder.getContext().setAuthentication(adminUserAuth) - assert impersonationAuthorizationService.canImpersonateUser(userService.loggedUserFromContext, user2.stringId) - impersonationService.impersonateUser(user2.stringId) - def impersonated = userService.loggedUser.getSelfOrImpersonated() - assert userService.loggedUser.isImpersonating() - assert impersonated.stringId == user2.stringId - assert impersonated.authorities.collect { it.stringId }.sort() == user2.authorities.collect { it.stringId }.sort() - assert impersonated.processRoles.collect { it.stringId }.sort() == user2.processRoles.collect { it.stringId }.sort() - } - - @Test - void testImpersonation() { - def config = setup() - assert impersonationAuthorizationService.canImpersonate(userService.loggedUserFromContext, config.stringId) - impersonationService.impersonateByConfig(config.stringId) - assert userService.loggedUser.isImpersonating() - assert userService.loggedUser.getSelfOrImpersonated().stringId == user2.stringId - - impersonationService.endImpersonation() - assert !userService.loggedUser.isImpersonating() - } - - @Test - void testImpersonationRolesAndAuths() { - def role = user2.processRoles.find { it.importId == "test_role" } - def auth = user2.authorities.find { it.name == Authority.user } - def config = setup([role.stringId], [auth.stringId, authorityService.getOrCreate(Authority.admin).stringId]) - - impersonationService.impersonateByConfig(config.stringId) - def impersonatedRoles = userService.loggedUser.getImpersonated().getProcessRoles() - def impersonatedAuths = userService.loggedUser.getImpersonated().getAuthorities() - assert impersonatedRoles.size() == 2 && impersonatedRoles.any { it.stringId == role.stringId } - // default role counts - assert impersonatedAuths.size() == 1 && impersonatedAuths[0].stringId == auth.stringId - - def transformedUser = userService.loggedUser.transformToLoggedUser() - def transformedUserImpersonated = transformedUser.getSelfOrImpersonated() - assert transformedUser.isImpersonating() - assert transformedUserImpersonated.getProcessRoles().size() == 2 && transformedUserImpersonated.getProcessRoles().any { it == role.stringId } - // default role counts - assert transformedUserImpersonated.getAuthorities().size() == 1 && (transformedUserImpersonated.getAuthorities()[0] as Authority).stringId == auth.stringId - } - - @Test - void testTaskSearchAssignFinish() { - def config = setup() - impersonationService.impersonateByConfig(config.stringId) - - assert workflowAuthorizationService.canCallCreate(userService.loggedUserFromContext, testNet.stringId) - def testCase = createTestCase() - assert workflowAuthorizationService.canCallDelete(userService.loggedUserFromContext, testCase.stringId) - def testTask1 = loadTask(testCase, "t1") - - sleep(8000) // elastic - - def caseReq = new CaseSearchRequest() - caseReq.process = [new CaseSearchRequest.PetriNet(testCase.processIdentifier)] - def cases = elasticCaseService.search([caseReq], userService.loggedUser.transformToLoggedUser(), PageRequest.of(0, 1), LocaleContextHolder.locale, false) - assert !cases.content.isEmpty() - - def searchReq = new TaskSearchRequest() - searchReq.transitionId = ["t1"] - searchReq.useCase = [new TaskSearchCaseRequest(testCase.stringId, null)] - def tasks = taskService.search([searchReq], PageRequest.of(0, 1), userService.loggedUser.transformToLoggedUser(), LocaleContextHolder.locale, false) - assert tasks.content[0].stringId == testTask1.stringId - - assert taskAuthorizationService.canCallAssign(userService.loggedUserFromContext, testTask1.stringId) - taskService.assignTask(userService.loggedUser.transformToLoggedUser(), testTask1.stringId) - testTask1 = reloadTask(testTask1) - assert testTask1.userId == user2.stringId - - assert taskAuthorizationService.canCallSaveData(userService.loggedUserFromContext, testTask1.stringId) - assert taskAuthorizationService.canCallSaveFile(userService.loggedUserFromContext, testTask1.stringId) - - assert taskAuthorizationService.canCallFinish(userService.loggedUserFromContext, testTask1.stringId) - taskService.finishTask(userService.loggedUser.transformToLoggedUser(), testTask1.stringId) - } - - @Test - void testAuthorization() { - def config = setup() - sleep(4000) // elastic - - def logged = userService.loggedUser.transformToLoggedUser() - assert impersonationAuthorizationService.canImpersonate(logged, config.stringId) - assert impersonationAuthorizationService.canImpersonateUser(logged, user2.stringId) - - config.getDataSet().get("valid_to").rawValue = LocalDateTime.now().minusMinutes(1) - workflowService.save(config) - sleep(4000) - - assert !impersonationAuthorizationService.canImpersonate(logged, config.stringId) - assert !impersonationAuthorizationService.canImpersonateUser(logged, user2.stringId) - } - - @Test - void testAuthMe() { - def config = setup() - def result = mvc.perform(get("/api/auth/login") - .with(httpBasic(user1.email, "password")) - .contentType(MediaType.APPLICATION_JSON) - .characterEncoding("utf-8")) - .andExpect(status().isOk()) - .andReturn() - def token = result.response.getHeader(X_AUTH_TOKEN) - - result = mvc.perform(post("/api/impersonate/config/" + config.stringId) - .header(X_AUTH_TOKEN, token) - .contentType(MediaType.APPLICATION_JSON) - .characterEncoding("utf-8")) - .andExpect(status().isOk()) - .andReturn() - - result = mvc.perform(get("/api/user/me") - .header(X_AUTH_TOKEN, token) - .contentType(MediaType.APPLICATION_JSON) - .characterEncoding("utf-8")) - .andExpect(status().isOk()) - .andReturn() - - String string = result.getResponse().getContentAsString() - def json = new JsonSlurper().parse(string.getBytes()) - assert json["impersonated"] != null - - result = mvc.perform(post("/api/impersonate/clear") - .header(X_AUTH_TOKEN, token) - .contentType(MediaType.APPLICATION_JSON) - .characterEncoding("utf-8")) - .andExpect(status().isOk()) - .andReturn() - - result = mvc.perform(get("/api/user/me") - .header(X_AUTH_TOKEN, token) - .contentType(MediaType.APPLICATION_JSON) - .characterEncoding("utf-8")) - .andExpect(status().isOk()) - .andReturn() - - string = result.getResponse().getContentAsString() - json = new JsonSlurper().parse(string.getBytes()) - assert json["impersonated"] == null - } - - def setup(List roles = null, List auths = null) { - def config = createConfigCase(user2, user1.stringId, roles, auths) - SecurityContextHolder.getContext().setAuthentication(auth1) - return config - } - - def createConfigCase(IUser user, String impersonator, List roles = null, List auths = null) { - def caze = helper.createCase("config", petriNetService.getNewestVersionByIdentifier(ImpersonationRunner.IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER)) - def owner = new UserFieldValue(user) - caze.dataSet.get("impersonated").rawValue = owner - caze.dataSet.get("impersonated_email").rawValue = owner.email - caze.dataSet.get("config_owner").rawValue = new UserListFieldValue([owner]) - caze.dataSet.get("impersonators").rawValue = [impersonator] - caze.dataSet.get("impersonated_roles").rawValue = roles ?: user.processRoles.stringId as List - caze.dataSet.get("impersonated_authorities").rawValue = auths ?: user.authorities.stringId as List - caze.dataSet.get("valid_from").rawValue = LocalDateTime.now().minusDays(1) - - /* set options so elastic indexing works */ - ((MultichoiceMapField) caze.dataSet.get("impersonators")).options = [(impersonator): new I18nString(impersonator)] - ((MultichoiceMapField) caze.dataSet.get("impersonated_roles")).options = (caze.dataSet.get("impersonated_roles").rawValue as List).collectEntries { [(it): new I18nString(it as String)] } as Map - ((MultichoiceMapField) caze.dataSet.get("impersonated_authorities")).options = (caze.dataSet.get("impersonated_authorities").rawValue as List).collectEntries { [(it): new I18nString(it as String)] } as Map - caze = workflowService.save(caze) - def initTask = caze.getTaskStringId("t2") - taskService.assignTask(userService.system.transformToLoggedUser(), initTask) - taskService.finishTask(userService.system.transformToLoggedUser(), initTask) - return workflowService.findOne(caze.stringId) - } - - def createTestCase() { - return helper.createCase("test", testNet) - } - - def loadTask(Case caze, String trans) { - return taskService.findById(caze.getTaskStringId(trans)) - } - - def reloadTask(Task task) { - return taskService.findById(task.stringId) - } - -} diff --git a/src/test/groovy/com/netgrif/application/engine/importer/AllDataTransitionTest.groovy b/src/test/groovy/com/netgrif/application/engine/importer/AllDataTransitionTest.groovy index cf72ca4ca40..7710fb9d36d 100644 --- a/src/test/groovy/com/netgrif/application/engine/importer/AllDataTransitionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/importer/AllDataTransitionTest.groovy @@ -2,13 +2,14 @@ package com.netgrif.application.engine.importer import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.importer.service.AllDataConfiguration -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.Transition import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.SuperCreator -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome import groovy.transform.CompileStatic import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -48,9 +49,10 @@ class AllDataTransitionTest { @Test void testAllData() throws MissingPetriNetMetaDataException, IOException { - ImportPetriNetEventOutcome outcome = petriNetService.importPetriNet(resourceFile.inputStream, VersionType.MAJOR, superCreator.getLoggedSuper()); - assert outcome.getNet() != null; - PetriNet net = outcome.getNet() + ImportPetriNetEventOutcome outcome = petriNetService.importProcess(new ImportProcessParams(resourceFile.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().getActiveActorId())) + assert outcome.getProcess() != null + Process net = outcome.getProcess() assert net.transitions.size() == 3 Transition allData = net.getTransition(configuration.allData.id) diff --git a/src/test/groovy/com/netgrif/application/engine/importer/PredefinedRolesPermissionsTest.groovy b/src/test/groovy/com/netgrif/application/engine/importer/PredefinedRolesPermissionsTest.groovy index 86ef94f0e88..b55d0cfdf31 100644 --- a/src/test/groovy/com/netgrif/application/engine/importer/PredefinedRolesPermissionsTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/importer/PredefinedRolesPermissionsTest.groovy @@ -1,20 +1,23 @@ package com.netgrif.application.engine.importer import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants import com.netgrif.application.engine.importer.service.AllDataConfiguration -import com.netgrif.application.engine.importer.service.RoleFactory -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.importer.service.PermissionFactory +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission -import com.netgrif.application.engine.petrinet.domain.roles.RolePermission +import com.netgrif.application.engine.authorization.domain.permissions.CasePermission +import com.netgrif.application.engine.authorization.domain.permissions.TaskPermission +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.Task import com.netgrif.application.engine.workflow.domain.TaskPair -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CreateCaseEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import groovy.transform.CompileStatic @@ -52,10 +55,10 @@ class PredefinedRolesPermissionsTest { private ITaskService taskService @Autowired - private IProcessRoleService processRoleService + private IRoleService roleService @Autowired - private RoleFactory roleFactory + private PermissionFactory roleFactory @Autowired private AllDataConfiguration configuration @@ -114,13 +117,13 @@ class PredefinedRolesPermissionsTest { private String ANONYMOUS_ROLE_ID @BeforeEach - public void before() { + void before() { testHelper.truncateDbs() - assert processRoleService.defaultRole() != null - DEFAULT_ROLE_ID = processRoleService.defaultRole().stringId + assert roleService.findDefaultRole() != null + DEFAULT_ROLE_ID = roleService.findDefaultRole().stringId assert DEFAULT_ROLE_ID != null - assert processRoleService.anonymousRole() != null - ANONYMOUS_ROLE_ID = processRoleService.anonymousRole().stringId + assert roleService.findAnonymousRole() != null + ANONYMOUS_ROLE_ID = roleService.findAnonymousRole().stringId assert ANONYMOUS_ROLE_ID != null } @@ -129,102 +132,104 @@ class PredefinedRolesPermissionsTest { void definedDefaultRole() { testPermissions(definedDefaultRoleNet, [ (DEFAULT_ROLE_ID): [ - (ProcessRolePermission.VIEW) : true, - (ProcessRolePermission.DELETE): true, - (ProcessRolePermission.CREATE): true, + (CasePermission.VIEW) : true, + (CasePermission.DELETE): true, + (CasePermission.CREATE): true, ] - ] as Map>, [ + ] as Map>, [ (DEFAULT_ROLE_ID): [ - (RolePermission.ASSIGN) : true, - (RolePermission.CANCEL) : true, - (RolePermission.FINISH) : true, - (RolePermission.VIEW) : true, - (RolePermission.SET) : true, - (RolePermission.DELEGATE): true + (TaskPermission.ASSIGN) : true, + (TaskPermission.CANCEL) : true, + (TaskPermission.FINISH) : true, + (TaskPermission.VIEW) : true, +// TODO: release/8.0.0 +// (RolePermission.SET) : true, +// (TaskPermission.DELEGATE): true ] - ] as Map>, true, false) + ] as Map>, true, false) } @Test void shadowDefaultRole() { testPermissions(shadowedDefaultRoleNet, [ (NET_ROLE_ID): [ - (ProcessRolePermission.VIEW) : true, - (ProcessRolePermission.DELETE): true, + (CasePermission.VIEW) : true, + (CasePermission.DELETE): true, ] - ] as Map>, [ + ] as Map>, [ (NET_ROLE_ID): [ - (RolePermission.VIEW) : true, - (RolePermission.DELEGATE): true, + (TaskPermission.VIEW) : true, +// (TaskPermission.DELEGATE): true, ] - ] as Map>, true, false) + ] as Map>, true, false) } @Test void customDefaultRole() { testPermissions(customDefaultRoleNet, [ (DEFAULT_ROLE_ID): [ - (ProcessRolePermission.VIEW) : true, - (ProcessRolePermission.DELETE): true, + (CasePermission.VIEW) : true, + (CasePermission.DELETE): true, ] - ] as Map>, [ + ] as Map>, [ (DEFAULT_ROLE_ID): [ - (RolePermission.VIEW) : true, - (RolePermission.DELEGATE): true, + (TaskPermission.VIEW) : true, +// (TaskPermission.DELEGATE): true, ] - ] as Map>, true, false) + ] as Map>, true, false) } @Test void negativeDefaultRole() { testPermissions(negativeDefaultRoleNet, [ (DEFAULT_ROLE_ID): [ - (ProcessRolePermission.VIEW) : false, - (ProcessRolePermission.DELETE): false, + (CasePermission.VIEW) : false, + (CasePermission.DELETE): false, ] - ] as Map>, [ + ] as Map>, [ (DEFAULT_ROLE_ID): [ - (RolePermission.VIEW) : false, - (RolePermission.DELEGATE): false, + (TaskPermission.VIEW) : false, +// (TaskPermission.DELEGATE): false, ] - ] as Map>, true, false) + ] as Map>, true, false) } @Test void combinedDefaultRole() { testPermissions(combinedDefaultRoleNet, [ (DEFAULT_ROLE_ID): [ - (ProcessRolePermission.VIEW) : true, - (ProcessRolePermission.DELETE): true, + (CasePermission.VIEW) : true, + (CasePermission.DELETE): true, ], (NET_ROLE_ID) : [ - (ProcessRolePermission.VIEW) : false, - (ProcessRolePermission.DELETE): false, + (CasePermission.VIEW) : false, + (CasePermission.DELETE): false, ] - ] as Map>, [ + ] as Map>, [ (DEFAULT_ROLE_ID): [ - (RolePermission.VIEW) : true, - (RolePermission.DELEGATE): true, + (TaskPermission.VIEW) : true, +// (TaskPermission.DELEGATE): true, ], (NET_ROLE_ID) : [ - (RolePermission.VIEW) : false, - (RolePermission.DELEGATE): false, + (TaskPermission.VIEW) : false, +// (TaskPermission.DELEGATE): false, ] - ] as Map>, true, false) + ] as Map>, true, false) } @Test() void missingDefaultRole() { - testPermissions(missingDefaultRoleNet, [:] as Map>, [ + testPermissions(missingDefaultRoleNet, [:] as Map>, [ (DEFAULT_ROLE_ID): [ - (RolePermission.VIEW) : true, - (RolePermission.DELEGATE): true, + (TaskPermission.VIEW) : true, +// (TaskPermission.DELEGATE): true, ] - ] as Map>, false, false) + ] as Map>, false, false) } @Test() void reservedDefaultRole() { + // todo: release/8.0.0 implementation of importer ignores system roles, should it throw an exception? assertThrows(IllegalArgumentException.class, () -> { importAndCreate(reservedDefaultRoleNet) }); @@ -232,27 +237,27 @@ class PredefinedRolesPermissionsTest { @Test() void defaultShadowedByUserRef() { - testPermissions(shadowedUserRefDefaultRoleNet, [:] as Map>, [:] as Map>, true, false) + testPermissions(shadowedUserRefDefaultRoleNet, [:] as Map>, [:] as Map>, true, false) } @Test void disabledReferencedDefaultRole() { testPermissions(disabledReferencedDefaultRoleNet, [ (DEFAULT_ROLE_ID): [ - (ProcessRolePermission.VIEW) : true, - (ProcessRolePermission.DELETE): true, + (CasePermission.VIEW) : true, + (CasePermission.DELETE): true, ] - ] as Map>, [ + ] as Map>, [ (DEFAULT_ROLE_ID): [ - (RolePermission.VIEW) : true, - (RolePermission.DELEGATE): true, + (TaskPermission.VIEW) : true, +// (TaskPermission.DELEGATE): true, ] - ] as Map>, false, false) + ] as Map>, false, false) } @Test() void defaultShadowedByUsersRef() { - testPermissions(shadowedUsersRefDefaultRoleNet, [:] as Map>, [:] as Map>, true, false) + testPermissions(shadowedUsersRefDefaultRoleNet, [:] as Map>, [:] as Map>, true, false) } // ANONYMOUS ROLE ================================= @@ -260,100 +265,102 @@ class PredefinedRolesPermissionsTest { void definedAnonymousRole() { testPermissions(definedAnonymousRoleNet, [ (ANONYMOUS_ROLE_ID): [ - (ProcessRolePermission.VIEW) : true, - (ProcessRolePermission.CREATE): true, + (CasePermission.VIEW) : true, + (CasePermission.CREATE): true, ] - ] as Map>, [ + ] as Map>, [ (ANONYMOUS_ROLE_ID): [ - (RolePermission.ASSIGN): true, - (RolePermission.CANCEL): true, - (RolePermission.FINISH): true, - (RolePermission.VIEW) : true, - (RolePermission.SET) : true, + (TaskPermission.ASSIGN): true, + (TaskPermission.CANCEL): true, + (TaskPermission.FINISH): true, + (TaskPermission.VIEW) : true, +// TODO: release/8.0.0 +// (RolePermission.SET) : true, ] - ] as Map>, false, true) + ] as Map>, false, true) } @Test void shadowAnonymousRole() { testPermissions(shadowedAnonymousRoleNet, [ (NET_ROLE_ID): [ - (ProcessRolePermission.VIEW) : true, - (ProcessRolePermission.DELETE): true, + (CasePermission.VIEW) : true, + (CasePermission.DELETE): true, ] - ] as Map>, [ + ] as Map>, [ (NET_ROLE_ID): [ - (RolePermission.VIEW) : true, - (RolePermission.DELEGATE): true, + (TaskPermission.VIEW) : true, +// (TaskPermission.DELEGATE): true, ] - ] as Map>, false, true) + ] as Map>, false, true) } @Test void customAnonymousRole() { testPermissions(customAnonymousRoleNet, [ (ANONYMOUS_ROLE_ID): [ - (ProcessRolePermission.VIEW) : true, - (ProcessRolePermission.DELETE): true, + (CasePermission.VIEW) : true, + (CasePermission.DELETE): true, ] - ] as Map>, [ + ] as Map>, [ (ANONYMOUS_ROLE_ID): [ - (RolePermission.VIEW) : true, - (RolePermission.DELEGATE): true, + (TaskPermission.VIEW) : true, +// (TaskPermission.DELEGATE): true, ] - ] as Map>, false, true) + ] as Map>, false, true) } @Test void negativeAnonymousRole() { testPermissions(negativeAnonymousRoleNet, [ (ANONYMOUS_ROLE_ID): [ - (ProcessRolePermission.VIEW) : false, - (ProcessRolePermission.DELETE): false, + (CasePermission.VIEW) : false, + (CasePermission.DELETE): false, ] - ] as Map>, [ + ] as Map>, [ (ANONYMOUS_ROLE_ID): [ - (RolePermission.VIEW) : false, - (RolePermission.DELEGATE): false, + (TaskPermission.VIEW) : false, +// (TaskPermission.DELEGATE): false, ] - ] as Map>, false, true) + ] as Map>, false, true) } @Test void combinedAnonymousRole() { testPermissions(combinedAnonymousRoleNet, [ (ANONYMOUS_ROLE_ID): [ - (ProcessRolePermission.VIEW) : true, - (ProcessRolePermission.DELETE): true, + (CasePermission.VIEW) : true, + (CasePermission.DELETE): true, ], (NET_ROLE_ID) : [ - (ProcessRolePermission.VIEW) : false, - (ProcessRolePermission.DELETE): false, + (CasePermission.VIEW) : false, + (CasePermission.DELETE): false, ] - ] as Map>, [ + ] as Map>, [ (ANONYMOUS_ROLE_ID): [ - (RolePermission.VIEW) : true, - (RolePermission.DELEGATE): true, + (TaskPermission.VIEW) : true, +// (TaskPermission.DELEGATE): true, ], (NET_ROLE_ID) : [ - (RolePermission.VIEW) : false, - (RolePermission.DELEGATE): false, + (TaskPermission.VIEW) : false, +// (TaskPermission.DELEGATE): false, ] - ] as Map>, false, true) + ] as Map>, false, true) } @Test() void missingAnonymousRole() { - testPermissions(missingAnonymousRoleNet, [:] as Map>, [ + testPermissions(missingAnonymousRoleNet, [:] as Map>, [ (ANONYMOUS_ROLE_ID): [ - (RolePermission.VIEW) : true, - (RolePermission.DELEGATE): true, + (TaskPermission.VIEW) : true, +// (TaskPermission.DELEGATE): true, ] - ] as Map>, false, false) + ] as Map>, false, false) } @Test() void reservedAnonymousRole() { + // todo: release/8.0.0 implementation of importer ignores system roles, should it throw an exception? assertThrows(IllegalArgumentException.class, () -> { importAndCreate(reservedAnonymousRoleNet) }); @@ -361,27 +368,27 @@ class PredefinedRolesPermissionsTest { @Test() void anonymousShadowedByUserRef() { - testPermissions(shadowedUserRefAnonymousRoleNet, [:] as Map>, [:] as Map>, false, true) + testPermissions(shadowedUserRefAnonymousRoleNet, [:] as Map>, [:] as Map>, false, true) } @Test void disabledReferencedAnonymousRole() { testPermissions(disabledReferencedAnonymousRoleNet, [ (ANONYMOUS_ROLE_ID): [ - (ProcessRolePermission.VIEW) : true, - (ProcessRolePermission.DELETE): true, + (CasePermission.VIEW) : true, + (CasePermission.DELETE): true, ] - ] as Map>, [ + ] as Map>, [ (ANONYMOUS_ROLE_ID): [ - (RolePermission.VIEW) : true, - (RolePermission.DELEGATE): true, + (TaskPermission.VIEW) : true, +// (TaskPermission.DELEGATE): true, ] - ] as Map>, false, false) + ] as Map>, false, false) } @Test() void anonymousShadowedByUsersRef() { - testPermissions(shadowedUsersRefAnonymousRoleNet, [:] as Map>, [:] as Map>, false, true) + testPermissions(shadowedUsersRefAnonymousRoleNet, [:] as Map>, [:] as Map>, false, true) } // COMBINED ROLES ====================================== @@ -394,69 +401,79 @@ class PredefinedRolesPermissionsTest { void definedCombinedRole() { testPermissions(definedCombinedRoleNet, [ (DEFAULT_ROLE_ID) : [ - (ProcessRolePermission.VIEW) : true, - (ProcessRolePermission.DELETE): true, - (ProcessRolePermission.CREATE): true, + (CasePermission.VIEW) : true, + (CasePermission.DELETE): true, + (CasePermission.CREATE): true, ], (ANONYMOUS_ROLE_ID): [ - (ProcessRolePermission.VIEW) : true, - (ProcessRolePermission.CREATE): true, + (CasePermission.VIEW) : true, + (CasePermission.CREATE): true, ] - ] as Map>, [ + ] as Map>, [ (DEFAULT_ROLE_ID) : [ - (RolePermission.ASSIGN) : true, - (RolePermission.CANCEL) : true, - (RolePermission.FINISH) : true, - (RolePermission.VIEW) : true, - (RolePermission.SET) : true, - (RolePermission.DELEGATE): true + (TaskPermission.ASSIGN) : true, + (TaskPermission.CANCEL) : true, + (TaskPermission.FINISH) : true, + (TaskPermission.VIEW) : true, +// TODO: release/8.0.0 +// (RolePermission.SET) : true, +// (TaskPermission.DELEGATE): true ], (ANONYMOUS_ROLE_ID): [ - (RolePermission.ASSIGN): true, - (RolePermission.CANCEL): true, - (RolePermission.FINISH): true, - (RolePermission.VIEW) : true, - (RolePermission.SET) : true, + (TaskPermission.ASSIGN): true, + (TaskPermission.CANCEL): true, + (TaskPermission.FINISH): true, + (TaskPermission.VIEW) : true, +// TODO: release/8.0.0 +// (RolePermission.SET) : true, ] - ] as Map>, true, true) + ] as Map>, true, true) } - private void testPermissions(Resource model, Map> processPermissions, Map> taskPermissions, boolean defaultRoleEnabled, boolean anonymousRoleEnabled) { + private void testPermissions(Resource model, Map> processPermissions, Map> taskPermissions, boolean defaultRoleEnabled, boolean anonymousRoleEnabled) { NetCaseTask instances = importAndCreate(model) - String netRoleId = instances.net.getRoles().keySet().find({ it -> it != DEFAULT_ROLE_ID && it != ANONYMOUS_ROLE_ID }) - - Map> processPerms = transformProcessRolePermissionMap(processPermissions, netRoleId); - Map> taskPerms = transformRolePermissionMap(taskPermissions, netRoleId); - - def negativeProcessView = processPerms.findAll { it -> it.value.containsKey(ProcessRolePermission.VIEW) && !it.value.get(ProcessRolePermission.VIEW) }.collect { it -> it.key } - def negativeTaskView = taskPerms.findAll { it -> it.value.containsKey(RolePermission.VIEW) && !it.value.get(RolePermission.VIEW) }.collect { it -> it.key } - - assert instances.net.isDefaultRoleEnabled() == defaultRoleEnabled - assert instances.net.isAnonymousRoleEnabled() == anonymousRoleEnabled - assert instances.net.getPermissions() == processPerms - assert instances.net.negativeViewRoles == negativeProcessView - assert instances.net.getTransition(TRANSITION_ID).roles == taskPerms - assert instances.net.getTransition(TRANSITION_ID).negativeViewRoles == negativeTaskView - - processPerms = processPerms.findAll { it -> it.value.containsKey(ProcessRolePermission.VIEW) || it.value.containsKey(ProcessRolePermission.DELETE) } - processPerms.forEach({ k, v -> v.remove(ProcessRolePermission.CREATE) }) - - assert instances.aCase.getPermissions() == processPerms - assert instances.aCase.negativeViewRoles == negativeProcessView - - assert instances.task.getRoles() == taskPerms - assert instances.task.negativeViewRoles == negativeTaskView + // TODO: release/8.0.0 fix +// String netRoleId = instances.net.getRoles().keySet().find({ it -> it != DEFAULT_ROLE_ID && it != ANONYMOUS_ROLE_ID }) + String netRoleId = "" + + Map> processPerms = transformProcessRolePermissionMap(processPermissions, netRoleId); + Map> taskPerms = transformRolePermissionMap(taskPermissions, netRoleId); + + def negativeProcessView = processPerms.findAll { it -> it.value.containsKey(CasePermission.VIEW) && !it.value.get(CasePermission.VIEW) }.collect { it -> it.key } + def negativeTaskView = taskPerms.findAll { it -> it.value.containsKey(TaskPermission.VIEW) && !it.value.get(TaskPermission.VIEW) }.collect { it -> it.key } + +// TODO: release/8.0.0 +// assert instances.net.isDefaultRoleEnabled() == defaultRoleEnabled +// assert instances.net.isAnonymousRoleEnabled() == anonymousRoleEnabled +// assert instances.net.getPermissions() == processPerms +// assert instances.net.negativeViewRoles == negativeProcessView +// assert instances.net.getTransition(TRANSITION_ID).roles == taskPerms +// assert instances.net.getTransition(TRANSITION_ID).negativeViewRoles == negativeTaskView +// +// processPerms = processPerms.findAll { it -> it.value.containsKey(ProcessRolePermission.VIEW) || it.value.containsKey(ProcessRolePermission.DELETE) } +// processPerms.forEach({ k, v -> v.remove(ProcessRolePermission.CREATE) }) +// +// assert instances.aCase.getPermissions() == processPerms +// assert instances.aCase.negativeViewRoles == negativeProcessView +// +// assert instances.task.getPermissions() == taskPerms +// assert instances.task.negativeViewRoles == negativeTaskView } private NetCaseTask importAndCreate(Resource model) { - ImportPetriNetEventOutcome importOutcome = petriNetService.importPetriNet(model.inputStream, VersionType.MAJOR, superCreator.loggedSuper) + ImportPetriNetEventOutcome importOutcome = petriNetService.importProcess(new ImportProcessParams(model.inputStream, VersionType.MAJOR, superCreator.loggedSuper.activeActorId)) - assert importOutcome.getNet() != null + assert importOutcome.getProcess() != null - PetriNet net = importOutcome.getNet() + Process net = importOutcome.getProcess() - CreateCaseEventOutcome createCaseOutcome = workflowService.createCase(net.stringId, '', '', superCreator.loggedSuper) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title('') + .authorId(superCreator.loggedSuper.activeActorId) + .build() + CreateCaseEventOutcome createCaseOutcome = workflowService.createCase(createCaseParams) assert createCaseOutcome.getCase() != null Case aCase = createCaseOutcome.getCase() @@ -471,24 +488,25 @@ class PredefinedRolesPermissionsTest { return new NetCaseTask(net, aCase, task) } - private Map> transformProcessRolePermissionMap(Map> input, String netRoleId) { + // todo: release/8.0.0 method name + private Map> transformProcessRolePermissionMap(Map> input, String netRoleId) { return input.collectEntries { it -> [it.key == DEFAULT_ROLE_ID || it.key == ANONYMOUS_ROLE_ID ? it.key : netRoleId, it.value.collectEntries { ti -> [ti.key, ti.value] }] - } as Map> + } as Map> } - private Map> transformRolePermissionMap(Map> input, String netRoleId) { + private Map> transformRolePermissionMap(Map> input, String netRoleId) { return input.collectEntries { it -> [it.key == DEFAULT_ROLE_ID || it.key == ANONYMOUS_ROLE_ID ? it.key : netRoleId, it.value.collectEntries { ti -> [ti.key, ti.value] }] - } as Map> + } as Map> } private class NetCaseTask { - PetriNet net + Process net Case aCase Task task - NetCaseTask(PetriNet net, Case aCase, Task task) { + NetCaseTask(Process net, Case aCase, Task task) { this.net = net this.aCase = aCase this.task = task diff --git a/src/test/groovy/com/netgrif/application/engine/importer/UserListTest.groovy b/src/test/groovy/com/netgrif/application/engine/importer/UserListTest.groovy index 8c05133e2e0..1cee1bcba56 100644 --- a/src/test/groovy/com/netgrif/application/engine/importer/UserListTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/importer/UserListTest.groovy @@ -1,20 +1,25 @@ package com.netgrif.application.engine.importer import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.authorization.domain.Role +import com.netgrif.application.engine.authorization.domain.User +import com.netgrif.application.engine.authorization.service.interfaces.IUserService +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.dataset.Field import com.netgrif.application.engine.petrinet.domain.dataset.UserFieldValue import com.netgrif.application.engine.petrinet.domain.dataset.UserListField import com.netgrif.application.engine.petrinet.domain.dataset.UserListFieldValue +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.utils.FullPageRequest import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.QCase import com.netgrif.application.engine.workflow.domain.Task -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.params.SetDataParams import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.ITaskService @@ -37,22 +42,28 @@ import java.util.stream.Collectors class UserListTest { @Autowired - private TestHelper testHelper; + private TestHelper testHelper @Autowired - private IPetriNetService petriNetService; + private IPetriNetService petriNetService @Autowired - private SuperCreator superCreator; + private SuperCreator superCreator @Autowired - private CaseRepository caseRepository; + private CaseRepository caseRepository @Autowired - private IDataService dataService; + private IDataService dataService @Autowired - private ITaskService taskService; + private ITaskService taskService + + @Autowired + private IUserService userService + + @Autowired + private IRoleService roleService @BeforeEach void before() { @@ -61,9 +72,11 @@ class UserListTest { @Test void testUserList() throws MissingPetriNetMetaDataException, IOException { - ImportPetriNetEventOutcome net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/user_list.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); + TestHelper.login(superCreator.superIdentity) + ImportPetriNetEventOutcome net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/user_list.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) - assert net.getNet() != null; + assert net.getProcess() != null; Optional caseOpt = caseRepository.findOne(QCase.case$.title.eq("User List")); assert caseOpt.isPresent(); @@ -71,11 +84,13 @@ class UserListTest { Task task = taskService.findByCases(new FullPageRequest(), Collections.singletonList(caseOpt.get().getStringId())).stream().collect(Collectors.toList()).get(0) - dataService.setData(task.stringId, new DataSet([ - "users_1": new UserListField(rawValue: new UserListFieldValue(new UserFieldValue(superCreator.getSuperUser()))) - ] as Map>), superCreator.getLoggedSuper()) + User user = userService.findById(superCreator.getLoggedSuper().activeActorId).get() + dataService.setData(new SetDataParams(task.stringId, new DataSet([ + "users_1": new UserListField(rawValue: new UserListFieldValue(new UserFieldValue(user))) + ] as Map>), superCreator.getLoggedSuper().getActiveActorId())) - assert taskService.findById(task.stringId).users.get(superCreator.getSuperUser().getStringId()) - assert caseRepository.findById(caseOpt.get().stringId).get().users.get(superCreator.getSuperUser().getStringId()) + Role caseRole = roleService.findCaseRoleByCaseIdAndImportId(caseOpt.get().stringId, "users_1") + assert taskService.findById(task.stringId).caseRolePermissions.containsKey(caseRole.stringId) + assert caseRepository.findById(caseOpt.get().stringId).get().caseRolePermissions.containsKey(caseRole.stringId) } } diff --git a/src/test/groovy/com/netgrif/application/engine/integration/dashboard/DashboardServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/integration/dashboard/DashboardServiceTest.groovy index f99c6251aa9..ac719a0cc79 100644 --- a/src/test/groovy/com/netgrif/application/engine/integration/dashboard/DashboardServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/integration/dashboard/DashboardServiceTest.groovy @@ -1,7 +1,7 @@ package com.netgrif.application.engine.integration.dashboard import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper @@ -22,10 +22,10 @@ import org.springframework.test.context.junit.jupiter.SpringExtension class DashboardServiceTest { @Autowired - IWorkflowService workflowService + private IWorkflowService workflowService @Autowired - ImportHelper helper + private ImportHelper helper @Autowired private IPetriNetService petriNetService @@ -42,11 +42,13 @@ class DashboardServiceTest { @BeforeEach void setup() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void dashboardIntegerTest() { - PetriNet net1 = helper.createNet("all_data.xml", VersionType.MAJOR).get() + // todo: release/8.0.0 file petriNets/all_data.xml is empty + Process net1 = helper.createNet("all_data.xml", VersionType.MAJOR).get() Random random = new Random() (1..30).each { Case aCase = helper.createCase("Default title", net1) @@ -57,7 +59,8 @@ class DashboardServiceTest { @Test void dashboardStringTest() { - PetriNet net1 = helper.createNet("all_data.xml", VersionType.MAJOR).get() + // todo: release/8.0.0 file petriNets/all_data.xml is empty + Process net1 = helper.createNet("all_data.xml", VersionType.MAJOR).get() Random random = new Random() (1..30).each { Case aCase = helper.createCase("Default title", net1) diff --git a/src/test/groovy/com/netgrif/application/engine/ipc/AssignCancelFinishWithCaseTest.groovy b/src/test/groovy/com/netgrif/application/engine/ipc/AssignCancelFinishWithCaseTest.groovy index 00152437996..54e8a8e88bb 100644 --- a/src/test/groovy/com/netgrif/application/engine/ipc/AssignCancelFinishWithCaseTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/ipc/AssignCancelFinishWithCaseTest.groovy @@ -3,6 +3,7 @@ package com.netgrif.application.engine.ipc import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.importer.service.Importer import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator @@ -57,14 +58,15 @@ class AssignCancelFinishWithCaseTest { @Test void testAssignCancelFinish() { - def testNet = petriNetService.importPetriNet(stream(ASSIGN_CANCEL_FINISH_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) + def testNet = petriNetService.importProcess(new ImportProcessParams(stream(ASSIGN_CANCEL_FINISH_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) - assert testNet.getNet() != null + assert testNet.getProcess() != null - Case aCase = importHelper.createCase("Case 1", testNet.getNet()) + TestHelper.login(superCreator.superIdentity) + Case aCase = importHelper.createCase("Case 1", testNet.getProcess()) importHelper.assignTaskToSuper("Task", aCase.stringId) - def cases = caseRepository.findAllByProcessIdentifier(testNet.getNet().identifier) + def cases = caseRepository.findAllByProcessIdentifier(testNet.getProcess().identifier) assert cases.find { it.title == "Case 2" }.dataSet.get("field").rawValue == 1 } } \ No newline at end of file diff --git a/src/test/groovy/com/netgrif/application/engine/ipc/CaseApiTest.groovy b/src/test/groovy/com/netgrif/application/engine/ipc/CaseApiTest.groovy index 673f585d081..90fa398d166 100644 --- a/src/test/groovy/com/netgrif/application/engine/ipc/CaseApiTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/ipc/CaseApiTest.groovy @@ -3,11 +3,12 @@ package com.netgrif.application.engine.ipc import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.importer.service.Importer import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -49,21 +50,22 @@ class CaseApiTest { @BeforeEach void setup() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } public static final String CREATE_NET_FILE = "ipc_createCase.xml" @Test void testCreate() { - testNet = petriNetService.importPetriNet(stream(CREATE_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) + testNet = petriNetService.importProcess(new ImportProcessParams(stream(CREATE_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) - assert testNet.getNet() != null + assert testNet.getProcess() != null - Case aCase = importHelper.createCase("Case 1", testNet.getNet()) + Case aCase = importHelper.createCase("Case 1", testNet.getProcess()) importHelper.assignTaskToSuper("Task", aCase.stringId) importHelper.finishTaskAsSuper("Task", aCase.stringId) - assert caseRepository.findAllByProcessIdentifier(testNet.getNet().identifier).size() > 1 + assert caseRepository.findAllByProcessIdentifier(testNet.getProcess().identifier).size() > 1 } public static final String SEARCH_NET_FILE = "ipc_where.xml" @@ -72,13 +74,13 @@ class CaseApiTest { void testSearch() { testHelper.truncateDbs() - testNet = petriNetService.importPetriNet(stream(SEARCH_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) + testNet = petriNetService.importProcess(new ImportProcessParams(stream(SEARCH_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) - assert testNet.getNet() != null + assert testNet.getProcess() != null List cases = [] 5.times { index -> - cases << importHelper.createCase("Case $index" as String, testNet.getNet()) + cases << importHelper.createCase("Case $index" as String, testNet.getProcess()) } importHelper.assignTaskToSuper("Task", cases[0].stringId) diff --git a/src/test/groovy/com/netgrif/application/engine/ipc/TaskApiTest.groovy b/src/test/groovy/com/netgrif/application/engine/ipc/TaskApiTest.groovy index f2714cc937f..7d7850a8ef1 100644 --- a/src/test/groovy/com/netgrif/application/engine/ipc/TaskApiTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/ipc/TaskApiTest.groovy @@ -1,15 +1,16 @@ package com.netgrif.application.engine.ipc import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService + import com.netgrif.application.engine.history.domain.baseevent.EventLog import com.netgrif.application.engine.history.domain.baseevent.repository.EventLogRepository import com.netgrif.application.engine.importer.service.Importer -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.dataset.Field import com.netgrif.application.engine.petrinet.domain.dataset.NumberField import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator @@ -44,9 +45,6 @@ class TaskApiTest { @Autowired private TaskRepository taskRepository - @Autowired - private IUserService userService - @Autowired private EventLogRepository eventLogRepository @@ -70,6 +68,7 @@ class TaskApiTest { testHelper.truncateDbs() initialised = true } + TestHelper.login(superCreator.superIdentity) } public static final String TASK_SEARCH_NET_FILE = "ipc_task_search.xml" @@ -77,11 +76,12 @@ class TaskApiTest { @Test @Disabled("GroovyRuntime Could not find matching constructor") void testTaskSearch() { - def netOptional = petriNetService.importPetriNet(stream(TASK_SEARCH_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) + def netOptional = petriNetService.importProcess(new ImportProcessParams(stream(TASK_SEARCH_NET_FILE), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) - assert netOptional.getNet() != null + assert netOptional.getProcess() != null - PetriNet net = netOptional.getNet() + Process net = netOptional.getProcess() 5.times { helper.createCase(TASK_EVENTS_NET_TITLE, net) } @@ -108,11 +108,12 @@ class TaskApiTest { @Test @Disabled() void testTaskEventActions() { - def netOptional = petriNetService.importPetriNet(stream(TASK_EVENTS_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) + def netOptional = petriNetService.importProcess(new ImportProcessParams(stream(TASK_EVENTS_NET_FILE), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) - assert netOptional.getNet() != null + assert netOptional.getProcess() != null - PetriNet net = netOptional.getNet() + Process net = netOptional.getProcess() Case useCase = helper.createCase(TASK_EVENTS_NET_TITLE, net) helper.assignTaskToSuper(TASK_EVENTS_TASK, useCase.stringId) helper.finishTaskAsSuper(TASK_EVENTS_TASK, useCase.stringId) @@ -141,22 +142,23 @@ class TaskApiTest { @Test @Disabled("spusta 2 krat") void testTaskExecution() { - def limitsNetOptional = petriNetService.importPetriNet(stream(LIMITS_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - def leasingNetOptional = petriNetService.importPetriNet(stream(LEASING_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) + def limitsNetOptional = petriNetService.importProcess(new ImportProcessParams(stream(LIMITS_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) + def leasingNetOptional = petriNetService.importProcess(new ImportProcessParams(stream(LEASING_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) - assert limitsNetOptional.getNet() != null - assert leasingNetOptional.getNet() != null + assert limitsNetOptional.getProcess() != null + assert leasingNetOptional.getProcess() != null - PetriNet limitsNet = limitsNetOptional.getNet() - PetriNet leasingNet = leasingNetOptional.getNet() + Process limitsNet = limitsNetOptional.getProcess() + Process leasingNet = leasingNetOptional.getProcess() Case limits = helper.createCase("Limits BA", limitsNet) Case leasing1 = helper.createCase("Leasing 1", leasingNet) Case leasing2 = helper.createCase("Leasing 2", leasingNet) + // TODO: release/8.0.0 helper.assignTaskToSuper(LEASING_NET_TASK_EDIT_COST, leasing1.stringId) helper.setTaskData(LEASING_NET_TASK_EDIT_COST, leasing1.stringId, [ - "1": [ + "data1": [ value: 30_000 as Double, type : helper.FIELD_NUMBER ] @@ -176,15 +178,15 @@ class TaskApiTest { //@formatter:off assert limits.dataSet.get("limit").rawValue as Double == 970_000 as Double - assert leasing1.dataSet.get("2").rawValue as Double == 970_000 as Double - assert leasing1.dataSet.get("1").rawValue as Double == 30_000 as Double - assert leasing2.dataSet.get("2").rawValue as Double == 970_000 as Double - assert leasing2.dataSet.get("1").rawValue as Double == 0 as Double + assert leasing1.dataSet.get("data2").rawValue as Double == 970_000 as Double + assert leasing1.dataSet.get("data1").rawValue as Double == 30_000 as Double + assert leasing2.dataSet.get("data2").rawValue as Double == 970_000 as Double + assert leasing2.dataSet.get("data1").rawValue as Double == 0 as Double //@formatter:on helper.assignTaskToSuper(LEASING_NET_TASK_EDIT_COST, leasing2.stringId) helper.setTaskData(LEASING_NET_TASK_EDIT_COST, leasing2.stringId, [ - "1": [ + "data1": [ value: 20_000 as Double, type : helper.FIELD_NUMBER ] @@ -203,10 +205,10 @@ class TaskApiTest { leasing2 = leasing2Opt.get() assert limits.dataSet.get("limit").rawValue as Double == 950_000 as Double - assert leasing1.dataSet.get("2").rawValue as Double == 950_000 as Double - assert leasing1.dataSet.get("1").rawValue as Double == 30_000 as Double - assert leasing2.dataSet.get("2").rawValue as Double == 950_000 as Double - assert leasing2.dataSet.get("1").rawValue as Double == 20_000 as Double + assert leasing1.dataSet.get("data2").rawValue as Double == 950_000 as Double + assert leasing1.dataSet.get("data1").rawValue as Double == 30_000 as Double + assert leasing2.dataSet.get("data2").rawValue as Double == 950_000 as Double + assert leasing2.dataSet.get("data1").rawValue as Double == 20_000 as Double } public static final String TASK_BULK_NET_FILE = "ipc_bulk.xml" @@ -216,10 +218,11 @@ class TaskApiTest { @Test void testTaskBulkActions() { - def netOptional = petriNetService.importPetriNet(stream(TASK_BULK_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) + def netOptional = petriNetService.importProcess(new ImportProcessParams(stream(TASK_BULK_NET_FILE), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) - assert netOptional.getNet() != null - PetriNet net = netOptional.getNet() + assert netOptional.getProcess() != null + Process net = netOptional.getProcess() 10.times { helper.createCase("Case $it", net) @@ -229,7 +232,7 @@ class TaskApiTest { helper.assignTaskToSuper(TASK_BULK_TASK, control.stringId) helper.finishTaskAsSuper(TASK_BULK_TASK, control.stringId) - assert taskRepository.findAll(QTask.task.userId.eq(userService.system.getStringId())).size() == 2 + assert taskRepository.findAll(QTask.task.assigneeId.eq(superCreator.loggedSuper.activeActorId)).size() == 2 } public static final String TASK_GETTER_NET_FILE = "ipc_data.xml" @@ -241,10 +244,11 @@ class TaskApiTest { @Test void testGetData() { - def netOptional = petriNetService.importPetriNet(stream(TASK_GETTER_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) + def netOptional = petriNetService.importProcess(new ImportProcessParams(stream(TASK_GETTER_NET_FILE), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) - assert netOptional.getNet() != null - PetriNet net = netOptional.getNet() + assert netOptional.getProcess() != null + Process net = netOptional.getProcess() def case1 = helper.createCase("Case 1", net) helper.setTaskData(TASK_GETTER_TASK, case1.stringId, new DataSet([ @@ -270,10 +274,11 @@ class TaskApiTest { @Test void testSetData() { - def netOptional = petriNetService.importPetriNet(stream(TASK_SETTER_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) + def netOptional = petriNetService.importProcess(new ImportProcessParams(stream(TASK_SETTER_NET_FILE), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) - assert netOptional.getNet() != null - PetriNet net = netOptional.getNet() + assert netOptional.getProcess() != null + Process net = netOptional.getProcess() def control = helper.createCase("Control case", net) def case1 = helper.createCase("Case 1", net) diff --git a/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy b/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy index 2ddad1eab53..ce1d8fc860e 100644 --- a/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy @@ -1,23 +1,21 @@ package com.netgrif.application.engine.menu import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.service.UserService -import com.netgrif.application.engine.orgstructure.groups.NextGroupService +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams import com.netgrif.application.engine.petrinet.domain.I18nString import com.netgrif.application.engine.petrinet.domain.dataset.FileFieldValue -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.petrinet.domain.dataset.TextField import com.netgrif.application.engine.startup.* import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.QCase import com.netgrif.application.engine.workflow.domain.QTask import com.netgrif.application.engine.workflow.domain.Task -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome import com.netgrif.application.engine.workflow.domain.menu.MenuAndFilters +import com.netgrif.application.engine.workflow.domain.params.SetDataParams import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository -import com.netgrif.application.engine.workflow.service.UserFilterSearchService +import com.netgrif.application.engine.workflow.service.ActorFilterSearchService import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.IMenuImportExportService import com.netgrif.application.engine.workflow.service.interfaces.ITaskService @@ -34,7 +32,6 @@ import org.springframework.security.core.context.SecurityContextHolder import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension - @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @SpringBootTest @@ -93,7 +90,7 @@ class MenuImportExportTest { DefaultFiltersRunner defaultFiltersRunner @Autowired - UserFilterSearchService userFilterSearchService + ActorFilterSearchService userFilterSearchService @Autowired ITaskService taskService @@ -101,22 +98,13 @@ class MenuImportExportTest { @Autowired private IDataService dataService - @Autowired - private GroupRunner groupRunner - - @Autowired - private UserService userService - @Autowired private CaseRepository caseRepository - @Autowired - private NextGroupService nextGroupService - @Autowired private SuperCreator superCreator - private User dummyUser; + private Identity dummyIdentity; private Authentication userAuth @@ -124,14 +112,14 @@ class MenuImportExportTest { void beforeTest() { this.testHelper.truncateDbs(); this.defaultFiltersRunner.run() - this.dummyUser = createDummyUser(); + this.dummyIdentity = createDummyIdentity(); } @Test @Disabled("Fix IllegalArgument") void testMenuImportExport() { - userAuth = new UsernamePasswordAuthenticationToken(dummyUser.transformToLoggedUser(), DUMMY_USER_PASSWORD) + userAuth = new UsernamePasswordAuthenticationToken(dummyIdentity.toSession(), DUMMY_USER_PASSWORD) SecurityContextHolder.getContext().setAuthentication(userAuth) def testNet = importHelper.createNet(TEST_NET) @@ -147,13 +135,13 @@ class MenuImportExportTest { workflowService.save(groupCase) QTask qTask = new QTask("task"); - Task task = taskService.searchOne(qTask.transitionId.eq(GROUP_NAV_TASK).and(qTask.caseId.eq(groupCase.stringId))); - dataService.setData(task, ImportHelper.populateDataset([ + Task task = taskService.searchOne(qTask.transitionId.eq(GROUP_NAV_TASK) & qTask.caseId.eq(groupCase.stringId)); + dataService.setData(new SetDataParams(task, ImportHelper.populateDataset([ (IMPORT_BUTTON_FIELD): [ "value": "1", "type" : "button" ] - ])) + ]), dummyIdentity.toSession().activeActorId)) Optional caseOpt = caseRepository.findOne(QCase.case$.title.eq(DUMMY_USER_GROUP_TITLE)) assert caseOpt.isPresent() groupCase = caseOpt.get() @@ -198,16 +186,18 @@ class MenuImportExportTest { assert Objects.equals(original, exported); } - private User createDummyUser() { - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - return importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: DUMMY_USER_PASSWORD, state: UserState.ACTIVE), - [auths.get("user")] as Authority[], - [] as ProcessRole[]) + private Identity createDummyIdentity() { + return importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Dummy")) + .lastname(new TextField("Identity")) + .username(new TextField(DUMMY_USER_MAIL)) + .password(new TextField(DUMMY_USER_PASSWORD)) + .build(), new ArrayList<>()) } private SetDataEventOutcome setData(task, Map> values) { - return dataService.setData(task, ImportHelper.populateDataset(values)) + return dataService.setData(new SetDataParams(task, ImportHelper.populateDataset(values), dummyIdentity.toSession().activeActorId)) } diff --git a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy deleted file mode 100644 index 43133d77fcd..00000000000 --- a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy +++ /dev/null @@ -1,109 +0,0 @@ -package com.netgrif.application.engine.orgstructure.groups - -import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.service.UserService -import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService -import com.netgrif.application.engine.petrinet.domain.PetriNet -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.startup.GroupRunner -import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.QCase -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.test.context.ActiveProfiles -import org.springframework.test.context.junit.jupiter.SpringExtension - -@ExtendWith(SpringExtension.class) -@ActiveProfiles(["test"]) -@SpringBootTest -class NextGroupServiceTest { - - public static final String DUMMY_USER_MAIL = "dummy@netgrif.com" - public static final String CUSTOMER_USER_MAIL = "customer@netgrif.com" - - @Autowired - INextGroupService nextGroupService - - @Autowired - GroupRunner groupRunner - - @Autowired - UserService userService - - @Autowired - private ImportHelper importHelper - - @Autowired - TestHelper testHelper - - @Test - void groupTest() { - testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], - [] as ProcessRole[]) - importHelper.createUser(new User(name: "Customer", surname: "User", email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], - [] as ProcessRole[]) - - Optional groupNet = importGroup() - assert groupNet.isPresent() - - - Case customGroup = createGroup() - if (customGroup == null) { - throw new NullPointerException() - } - - List allGroups = findAllGroups() - assert !allGroups.isEmpty() - - List byPredicate = findGroup() - assert !byPredicate.isEmpty() - - Case addedUserGroup = addUser() - assert !addedUserGroup.getDataSet().get("members").getOptions().isEmpty() - - Case removedUserGroup = removeUser() - assert !removedUserGroup.getDataSet().get("members").getOptions().isEmpty() - } - - Optional importGroup() { - return groupRunner.createDefaultGroup() - } - - Case createGroup() { - return nextGroupService.createGroup("CUSTOM_GROUP_1", userService.findByEmail(DUMMY_USER_MAIL, false)).getCase() - } - - List findGroup() { - QCase qCase = new QCase("case") - return nextGroupService.findByPredicate(qCase.author.email.eq(DUMMY_USER_MAIL)) - } - - List findAllGroups() { - return nextGroupService.findAllGroups() - } - - Case addUser() { - QCase qCase = new QCase("case") - Case group = nextGroupService.findByPredicate(qCase.title.eq("CUSTOM_GROUP_1")).get(0) - nextGroupService.addUser(userService.findByEmail(CUSTOMER_USER_MAIL, false), group) - nextGroupService.addUser(userService.findByEmail("engine@netgrif.com", false), group) - return group - } - - Case removeUser() { - QCase qCase = new QCase("case") - Case group = nextGroupService.findByPredicate(qCase.title.eq("CUSTOM_GROUP_1")).get(0) - nextGroupService.removeUser(userService.findByEmail(CUSTOMER_USER_MAIL, false), group) - return group - } -} diff --git a/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy b/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy index 0704ddb4991..29ac7a6448d 100644 --- a/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy @@ -1,26 +1,29 @@ package com.netgrif.application.engine.permissions import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.IUser -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService -import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authorization.domain.Role +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.dataset.Field import com.netgrif.application.engine.petrinet.domain.dataset.UserListField import com.netgrif.application.engine.petrinet.domain.dataset.UserListFieldValue -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.authorization.domain.ProcessRole +import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams +import com.netgrif.application.engine.workflow.domain.params.DeleteCaseParams +import com.netgrif.application.engine.workflow.domain.params.SetDataParams import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService @@ -50,18 +53,12 @@ class ElasticSearchViewPermissionTest { @Autowired private ITaskService taskService - @Autowired - private IUserService userService - @Autowired private SuperCreator superCreator @Autowired private ImportHelper importHelper - @Autowired - private IAuthorityService authorityService - @Autowired private IElasticCaseService elasticCaseService @@ -71,144 +68,197 @@ class ElasticSearchViewPermissionTest { @Autowired private IDataService dataService + @Autowired + private IRoleService roleService + @Autowired private TestHelper testHelper private static final String USER_EMAIL = "user123987645@test.com" - private PetriNet net - private PetriNet netWithUserRefs - private IUser testUser - private Authority userAuthority + private Process net + private Process netWithUserRefs + private Identity testIdentity @BeforeEach - void inti() { + void init() { testHelper.truncateDbs() - ImportPetriNetEventOutcome net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/view_permission_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null - this.net = net.getNet() - - ImportPetriNetEventOutcome netWithUserRefs = petriNetService.importPetriNet(new FileInputStream("src/test/resources/view_permission_with_userRefs_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert netWithUserRefs.getNet() != null - this.netWithUserRefs = netWithUserRefs.getNet() - - userAuthority = authorityService.getOrCreate(Authority.user) - - testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [userAuthority] as Authority[], [] as ProcessRole[]) + ImportPetriNetEventOutcome net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/view_permission_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) + assert net.getProcess() != null + this.net = net.getProcess() + + ImportPetriNetEventOutcome netWithUserRefs = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/view_permission_with_userRefs_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) + assert netWithUserRefs.getProcess() != null + this.netWithUserRefs = netWithUserRefs.getProcess() + + testIdentity = importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Role")) + .lastname(new TextField("Identity")) + .username(new TextField(USER_EMAIL)) + .password(new TextField("password")) + .build(), new ArrayList()) + + TestHelper.login(testIdentity) } @Test void testSearchElasticViewWithUserWithoutRole() { - Case case_ = workflowService.createCase(net.getStringId(), "Permission test", "", testUser.transformToLoggedUser()).getCase() + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Permission test") + .authorId(testIdentity.toSession().activeActorId) + .build() + Case case_ = workflowService.createCase(createCaseParams).getCase() CaseSearchRequest caseSearchRequest = new CaseSearchRequest() caseSearchRequest.process = [new CaseSearchRequest.PetriNet("vpt")] as List - Page casePage = elasticCaseService.search([caseSearchRequest] as List, testUser.transformToLoggedUser(), PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) + Page casePage = elasticCaseService.search([caseSearchRequest] as List, testIdentity.toSession().activeActorId, + PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) assert casePage.getContent().size() == 0 - workflowService.deleteCase(case_.getStringId()) + workflowService.deleteCase(new DeleteCaseParams(case_.getStringId())) } @Test void testSearchElasticViewWithUserWithPosRole() { - Case case_ = workflowService.createCase(net.getStringId(), "Permission test", "", testUser.transformToLoggedUser()).getCase() - ProcessRole posViewRole = this.net.getRoles().values().find(v -> v.getImportId() == "view_pos_role") - userService.addRole(testUser, posViewRole.getStringId()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Permission test") + .authorId(testIdentity.toSession().activeActorId) + .build() + Case case_ = workflowService.createCase(createCaseParams).getCase() + ProcessRole posViewRole = roleService.findProcessRoleByImportId("view_pos_role") + roleService.assignRolesToActor(testIdentity.toSession().activeActorId, Set.of(posViewRole.stringId)) CaseSearchRequest caseSearchRequest = new CaseSearchRequest() caseSearchRequest.process = [new CaseSearchRequest.PetriNet("vpt")] as List sleep(4000) - Page casePage = elasticCaseService.search([caseSearchRequest] as List, testUser.transformToLoggedUser(), PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) + Page casePage = elasticCaseService.search([caseSearchRequest] as List, testIdentity.toSession().activeActorId, + PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) assert casePage.getContent() != null assert casePage.getContent().size() == 1 assert casePage.getContent()[0].stringId == case_.stringId - userService.removeRole(testUser, posViewRole.getStringId()) - workflowService.deleteCase(case_.getStringId()) + roleService.removeRolesFromActor(testIdentity.toSession().activeActorId, Set.of(posViewRole.stringId)) + workflowService.deleteCase(new DeleteCaseParams(case_.getStringId())) } @Test void testSearchElasticViewWithUserWithNegRole() { - Case case_ = workflowService.createCase(net.getStringId(), "Permission test", "", testUser.transformToLoggedUser()).getCase() - ProcessRole negViewRole = this.net.getRoles().values().find(v -> v.getImportId() == "view_neg_role") - userService.addRole(testUser, negViewRole.getStringId()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Permission test") + .authorId(testIdentity.toSession().activeActorId) + .build() + Case case_ = workflowService.createCase(createCaseParams).getCase() + ProcessRole negViewRole = roleService.findProcessRoleByImportId("view_neg_role") + roleService.assignRolesToActor(testIdentity.toSession().activeActorId, Set.of(negViewRole.stringId)) CaseSearchRequest caseSearchRequest = new CaseSearchRequest() caseSearchRequest.process = [new CaseSearchRequest.PetriNet(net.getIdentifier())] as List - Page casePage = elasticCaseService.search([caseSearchRequest] as List, testUser.transformToLoggedUser(), PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) + Page casePage = elasticCaseService.search([caseSearchRequest] as List, testIdentity.toSession().activeActorId, + PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) - assert casePage.getContent().size() == 0 && case_.negativeViewRoles.contains(negViewRole.stringId) - userService.removeRole(testUser, negViewRole.getStringId()) - workflowService.deleteCase(case_.getStringId()) + // TODO: releas/8.0.0 negative view role + assert casePage.getContent().size() == 0 && case_.processRolePermissions.getPermissions().keySet().contains(negViewRole.stringId) + roleService.removeRolesFromActor(testIdentity.toSession().activeActorId, Set.of(negViewRole.stringId)) + workflowService.deleteCase(new DeleteCaseParams(case_.getStringId())) } @Test void testSearchElasticViewWithUserWithoutUserRef() { - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Permission test", "", testUser.transformToLoggedUser()).getCase() + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(netWithUserRefs) + .title("Permission test") + .authorId(testIdentity.toSession().activeActorId) + .build() + Case case_ = workflowService.createCase(createCaseParams).getCase() CaseSearchRequest caseSearchRequest = new CaseSearchRequest() caseSearchRequest.process = [new CaseSearchRequest.PetriNet(netWithUserRefs.getIdentifier())] as List - Page casePage = elasticCaseService.search([caseSearchRequest] as List, testUser.transformToLoggedUser(), PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) + Page casePage = elasticCaseService.search([caseSearchRequest] as List, testIdentity.toSession().activeActorId, + PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) assert casePage.getContent().size() == 0 - workflowService.deleteCase(case_.getStringId()) + workflowService.deleteCase(new DeleteCaseParams(case_.getStringId())) } @Test void testSearchElasticViewWithUserWithPosUserRef() { - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Permission test", "", testUser.transformToLoggedUser()).getCase() - String taskId = case_.getTaskStringId("1") - dataService.setData(taskId, new DataSet([ - "view_ul_pos": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(testUser.stringId)])) - ] as Map>), superCreator.getSuperUser()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(netWithUserRefs) + .title("Permission test") + .authorId(testIdentity.toSession().activeActorId) + .build() + Case case_ = workflowService.createCase(createCaseParams).getCase() + String taskId = case_.getTaskStringId("t1") + dataService.setData(new SetDataParams(taskId, new DataSet([ + "view_ul_pos": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(testIdentity.toSession().activeActorId)])) + ] as Map>), superCreator.getLoggedSuper().activeActorId)) case_ = workflowService.findOne(case_.stringId) sleep(4000) CaseSearchRequest caseSearchRequest = new CaseSearchRequest() caseSearchRequest.process = [new CaseSearchRequest.PetriNet(netWithUserRefs.getIdentifier())] as List - Page casePage = elasticCaseService.search([caseSearchRequest] as List, testUser.transformToLoggedUser(), PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) + Page casePage = elasticCaseService.search([caseSearchRequest] as List, testIdentity.toSession().activeActorId, + PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) - assert casePage.getContent().size() == 1 && casePage.getContent()[0].stringId == case_.stringId && case_.viewUsers.contains(testUser.getStringId()) - workflowService.deleteCase(case_.getStringId()) + // TODO: release/8.0.0 user view + assert casePage.getContent().size() == 1 && casePage.getContent()[0].stringId == case_.stringId && case_.caseRolePermissions.getPermissions().keySet().contains(testIdentity.toSession().activeActorId) + workflowService.deleteCase(new DeleteCaseParams(case_.getStringId())) } @Test void testSearchElasticViewWithUserWithNegUserRef() { - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Permission test", "", testUser.transformToLoggedUser()).getCase() - String taskId = case_.getTaskStringId("1") - dataService.setData(taskId, new DataSet([ - "view_ul_neg": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(testUser.stringId)])) - ] as Map>), superCreator.getSuperUser()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(netWithUserRefs) + .title("Permission test") + .authorId(testIdentity.toSession().activeActorId) + .build() + Case case_ = workflowService.createCase(createCaseParams).getCase() + String taskId = case_.getTaskStringId("t1") + dataService.setData(new SetDataParams(taskId, new DataSet([ + "view_ul_neg": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(testIdentity.toSession().activeActorId)])) + ] as Map>), superCreator.getLoggedSuper().activeActorId)) case_ = workflowService.findOne(case_.stringId) sleep(4000) CaseSearchRequest caseSearchRequest = new CaseSearchRequest() caseSearchRequest.process = [new CaseSearchRequest.PetriNet(netWithUserRefs.getIdentifier())] as List - Page casePage = elasticCaseService.search([caseSearchRequest] as List, testUser.transformToLoggedUser(), PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) - - assert casePage.getContent().size() == 0 && case_.negativeViewUsers.contains(testUser.getStringId()) - workflowService.deleteCase(case_.getStringId()) + Page casePage = elasticCaseService.search([caseSearchRequest] as List, testIdentity.toSession().activeActorId, + PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) + // TODO: release/8.0.0 negative view user + assert casePage.getContent().size() == 0 && case_.caseRolePermissions.getPermissions().keySet().contains(testIdentity.toSession().activeActorId) + workflowService.deleteCase(new DeleteCaseParams(case_.getStringId())) } @Test void testSearchElasticViewWithUserWithNegativeRoleAndPosUserRef() { - Case case_ = workflowService.createCase(netWithUserRefs.getStringId(), "Permission test", "", testUser.transformToLoggedUser()).getCase() - ProcessRole negViewRole = this.net.getRoles().values().find(v -> v.getImportId() == "view_neg_role") - userService.addRole(testUser, negViewRole.getStringId()) - String taskId = case_.getTaskStringId("1") - dataService.setData(taskId, new DataSet([ - "view_ul_pos": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(testUser.stringId)])) - ] as Map>), superCreator.getSuperUser()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(netWithUserRefs) + .title("Permission test") + .authorId(testIdentity.toSession().activeActorId) + .build() + Case case_ = workflowService.createCase(createCaseParams).getCase() + ProcessRole negViewRole = roleService.findProcessRoleByImportId("view_neg_role") + roleService.assignRolesToActor(testIdentity.toSession().activeActorId, Set.of(negViewRole.stringId)) + String taskId = case_.getTaskStringId("t1") + dataService.setData(new SetDataParams(taskId, new DataSet([ + "view_ul_pos": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(testIdentity.toSession().activeActorId)])) + ] as Map>), superCreator.getLoggedSuper().activeActorId)) case_ = workflowService.findOne(case_.stringId) sleep(4000) CaseSearchRequest caseSearchRequest = new CaseSearchRequest() caseSearchRequest.process = [new CaseSearchRequest.PetriNet(netWithUserRefs.getIdentifier())] as List - Page casePage = elasticCaseService.search([caseSearchRequest] as List, testUser.transformToLoggedUser(), PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) + Page casePage = elasticCaseService.search([caseSearchRequest] as List, testIdentity.toSession().activeActorId, + PageRequest.of(0, 20), LocaleContextHolder.getLocale(), false) - assert casePage.getContent().size() == 1 && case_.viewUsers.contains(testUser.stringId) - userService.removeRole(testUser, negViewRole.getStringId()) - workflowService.deleteCase(case_.getStringId()) + // TODO: release/8.0.0 view user + assert casePage.getContent().size() == 1 && case_.caseRolePermissions.containsKey(testIdentity.toSession().activeActorId) + roleService.removeRolesFromActor(testIdentity.toSession().activeActorId, Set.of(negViewRole.stringId)) + workflowService.deleteCase(new DeleteCaseParams(case_.getStringId())) } } diff --git a/src/test/groovy/com/netgrif/application/engine/insurance/EncryptionTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/EncryptionTest.groovy similarity index 66% rename from src/test/groovy/com/netgrif/application/engine/insurance/EncryptionTest.groovy rename to src/test/groovy/com/netgrif/application/engine/petrinet/EncryptionTest.groovy index e31d83ac9b4..12fe3e343f7 100644 --- a/src/test/groovy/com/netgrif/application/engine/insurance/EncryptionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/EncryptionTest.groovy @@ -1,15 +1,16 @@ -package com.netgrif.application.engine.insurance +package com.netgrif.application.engine.petrinet -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.LoggedUser -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService +import com.netgrif.application.engine.MockService +import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.configuration.properties.SuperAdminConfiguration import com.netgrif.application.engine.importer.service.Importer import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import com.netgrif.application.engine.workflow.service.TaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService @@ -37,23 +38,28 @@ class EncryptionTest { @Autowired private Importer importer - @Autowired - private IAuthorityService authorityService - @Autowired private IPetriNetService petriNetService @Autowired private SuperCreator superCreator + @Autowired + private MockService mockService + @Autowired private SuperAdminConfiguration configuration + @Autowired + private TestHelper testHelper + private final String FIELD_NAME = "City" private final String FIELD_VALUE = "Bratislava" @Test void testEncryption() { + TestHelper.login(superCreator.superIdentity) + String id = createCase() Case useCase = loadCase(id) @@ -62,7 +68,7 @@ class EncryptionTest { } private void assertCorrectEncrypting(Case useCase) { - def nameField = useCase.petriNet.dataSet.values().find { v -> v.name == FIELD_NAME } + def nameField = useCase.process.dataSet.values().find { v -> v.title == FIELD_NAME } // TODO: release/8.0.0 // DataField field = useCase.dataSet.get(nameField.stringId) // assert field.value == FIELD_VALUE @@ -82,17 +88,18 @@ class EncryptionTest { } private String createCase() { - ImportPetriNetEventOutcome net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/mapping_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null - def useCase = workflowService.createCase(net.getNet().stringId, "Encryption test", "color", mockLoggedUser()).getCase() - def nameField = useCase.petriNet.dataSet.values().find { v -> v.name.defaultValue == FIELD_NAME } + ImportPetriNetEventOutcome net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/mapping_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) + assert net.getProcess() != null + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net.getProcess()) + .title("Encryption test") + .authorId(mockService.mockLoggedIdentity().activeActorId) + .build() + def useCase = workflowService.createCase(createCaseParams).getCase() + def nameField = useCase.process.dataSet.values().find { v -> v.title.defaultValue == FIELD_NAME } // TODO: release/8.0.0 // useCase.dataSet.put(nameField.stringId, new DataField(FIELD_VALUE)) return workflowService.save(useCase).stringId } - - LoggedUser mockLoggedUser() { - def authorityUser = authorityService.getOrCreate(Authority.user) - return new LoggedUser(superCreator.getSuperUser().getStringId(), configuration.email, configuration.password, [authorityUser]) - } } \ No newline at end of file diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ActionRefTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ActionRefTest.groovy index 274811c005e..782ec831616 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ActionRefTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ActionRefTest.groovy @@ -1,7 +1,7 @@ package com.netgrif.application.engine.petrinet.domain import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.repositories.UserRepository +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.SuperCreator @@ -40,10 +40,7 @@ class ActionRefTest { private SuperCreator superCreator @Autowired - private IPetriNetService petriNetService; - - @Autowired - private UserRepository userRepository + private IPetriNetService petriNetService @Autowired private TestHelper testHelper @@ -57,7 +54,8 @@ class ActionRefTest { @Disabled("TODO: deprecated action ref") void testEventImport() { - PetriNet net = petriNetService.importPetriNet(new FileInputStream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet() + Process net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream(NET_FILE), VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert net.dataSet.get("text_1").events.size() == 8 assert net.transitions.get("task").dataSet.get("text_1").events.size() == 8 diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ArcOrderTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ArcOrderTest.groovy index 87eabc8fb30..5edc4396678 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ArcOrderTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ArcOrderTest.groovy @@ -4,6 +4,7 @@ import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.importer.service.Importer import com.netgrif.application.engine.petrinet.domain.arcs.ArcOrderComparator import com.netgrif.application.engine.petrinet.domain.arcs.ResetArc +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator @@ -21,7 +22,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension class ArcOrderTest { public static final String NET_FILE = "arc_order_test.xml" - public static final String NET_TASK = "1" + public static final String NET_TASK = "t1" @Autowired private Importer importer @@ -42,23 +43,22 @@ class ArcOrderTest { return ArcOrderTest.getClassLoader().getResourceAsStream(name) } - @BeforeEach void before() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void testOrder() { - def net = petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet() + def net = petriNetService.importProcess(new ImportProcessParams(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() - def arcs = net.getArcsOfTransition(NET_TASK) + def arcs = net.getInputArcsOf(NET_TASK) def sorted = arcs.sort { a1, a2 -> ArcOrderComparator.getInstance().compare(a1, a2) } assert sorted.last() instanceof ResetArc def instance = helper.createCase("Arc Case", net) helper.assignTaskToSuper(NET_TASK, instance.stringId) - assert true } } \ No newline at end of file diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ArcReferenceTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ArcReferenceTest.groovy index 039547d2014..5aa96625e73 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ArcReferenceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ArcReferenceTest.groovy @@ -1,6 +1,6 @@ package com.netgrif.application.engine.petrinet.domain -import com.netgrif.application.engine.auth.service.interfaces.IUserService + import com.netgrif.application.engine.importer.service.Importer import com.netgrif.application.engine.startup.ImportHelper import org.junit.jupiter.api.Test @@ -31,24 +31,19 @@ class ArcReferenceTest { @Autowired private ImportHelper helper - @Autowired - private IUserService userService - private def stream = { String name -> return ArcOrderTest.getClassLoader().getResourceAsStream(name) } @Test void testReference() { - def net = importer.importPetriNet(stream(NET_FILE)).get() - - assert net + assert importer.importPetriNet(stream(NET_FILE)).process } @Test void testInvalidReference() { assertThrows(IllegalArgumentException.class, () -> { - importer.importPetriNet(stream(NET_INVALID_FILE)).get() + importer.importPetriNet(stream(NET_INVALID_FILE)) }); } } \ No newline at end of file diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/EventTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/EventTest.groovy index e5fd604d828..e6e8c24c454 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/EventTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/EventTest.groovy @@ -1,18 +1,18 @@ package com.netgrif.application.engine.petrinet.domain import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.repositories.UserRepository import com.netgrif.application.engine.importer.service.Importer import com.netgrif.application.engine.ipc.TaskApiTest +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.DefaultRoleRunner + import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.startup.SystemUserRunner import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.taskoutcomes.TaskEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.TaskEventOutcome import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import com.netgrif.application.engine.workflow.domain.repositories.TaskRepository import com.netgrif.application.engine.workflow.service.TaskService @@ -60,20 +60,14 @@ class EventTest { @Autowired private SuperCreator superCreator - @Autowired - private DefaultRoleRunner roleRunner - @Autowired private MongoTemplate template - @Autowired - private UserRepository userRepository - @Autowired private SystemUserRunner userRunner @Autowired - private IPetriNetService petriNetService; + private IPetriNetService petriNetService @Autowired private TestHelper testHelper @@ -87,8 +81,10 @@ class EventTest { @Test void testEventImport() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) - PetriNet net = petriNetService.importPetriNet(stream(EVENT_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet() + Process net = petriNetService.importProcess(new ImportProcessParams(stream(EVENT_NET_FILE), VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() instance = helper.createCase(EVENT_NET_CASE, net) outcome = helper.assignTaskToSuper(EVENT_NET_TASK, instance.stringId) diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/FunctionsTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/FunctionsTest.groovy index 9ad9061ecb6..27a26e93f2f 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/FunctionsTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/FunctionsTest.groovy @@ -1,12 +1,16 @@ package com.netgrif.application.engine.petrinet.domain import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.IUser -import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService import com.netgrif.application.engine.petrinet.domain.dataset.* +import com.netgrif.application.engine.petrinet.domain.params.DeleteProcessParams +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams +import com.netgrif.application.engine.workflow.domain.params.SetDataParams import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService @@ -31,9 +35,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows @CompileStatic class FunctionsTest { - @Autowired - private IUserService userService - @Autowired private IDataService dataService @@ -46,6 +47,9 @@ class FunctionsTest { @Autowired private IPetriNetService petriNetService + @Autowired + private IIdentityService identityService + @Autowired private SuperCreator superCreator @@ -83,66 +87,92 @@ class FunctionsTest { @BeforeEach void before() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void testNamespaceFunction() { - assert userService.findByEmail("test@test.com") == null + assert identityService.findByUsername("test@test.com").isEmpty() - def functionResNet = petriNetService.importPetriNet(functionResNetResource.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() - def functionTestNet = petriNetService.importPetriNet(functionTestNetResource.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() + def functionResNet = petriNetService.importProcess(new ImportProcessParams(functionResNetResource.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() + def functionTestNet = petriNetService.importProcess(new ImportProcessParams(functionTestNetResource.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert functionResNet assert functionTestNet - Case aCase = workflowService.createCase(functionTestNet.stringId, "Test", "", userService.getLoggedOrSystem().transformToLoggedUser()).getCase() - dataService.setData(aCase.getTaskStringId("1"), new DataSet(["createUser": new BooleanField(rawValue: true)] as Map>), superCreator.getLoggedSuper()) - - IUser user = userService.findByEmail("test@test.com") - assert user - - userService.deleteUser(user) - petriNetService.deletePetriNet(functionResNet.stringId, userService.getLoggedOrSystem().transformToLoggedUser()) - petriNetService.deletePetriNet(functionTestNet.stringId, userService.getLoggedOrSystem().transformToLoggedUser()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(functionTestNet) + .title("Test") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case aCase = workflowService.createCase(createCaseParams).getCase() + dataService.setData(new SetDataParams(aCase.getTaskStringId("t1"), new DataSet(["createUser": new BooleanField(rawValue: true)] as Map>), + superCreator.getLoggedSuper().activeActorId)) + + Optional identityOpt = identityService.findByUsername("test@test.com") + assert identityOpt.isPresent() + + // todo: release/8.0.0 removal +// userService.deleteUser(user) + petriNetService.deleteProcess(new DeleteProcessParams(functionResNet.stringId)) + petriNetService.deleteProcess(new DeleteProcessParams(functionTestNet.stringId)) } @Test void testProcessFunctions() { - def functionResNet = petriNetService.importPetriNet(functionResNetResource.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() - def functionTestNet = petriNetService.importPetriNet(functionTestNetResource.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() + def functionResNet = petriNetService.importProcess(new ImportProcessParams(functionResNetResource.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() + def functionTestNet = petriNetService.importProcess(new ImportProcessParams(functionTestNetResource.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert functionResNet assert functionTestNet - Case aCase = workflowService.createCase(functionTestNet.stringId, "Test", "", userService.getLoggedOrSystem().transformToLoggedUser()).getCase() - dataService.setData(aCase.getTaskStringId("1"), new DataSet((["enum": new EnumerationField(rawValue: new I18nString("ano"))] as Map>)), superCreator.getLoggedSuper()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(functionTestNet) + .title("Test") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case aCase = workflowService.createCase(createCaseParams).getCase() + dataService.setData(new SetDataParams(aCase.getTaskStringId("t1"), new DataSet((["enum": new EnumerationField(rawValue: new I18nString("ano"))] as Map>)), + superCreator.getLoggedSuper().activeActorId)) aCase = workflowService.findOne(aCase.getStringId()) NumberField field = aCase.getDataSet().get("number") as NumberField - assert field.getBehaviors().get("1").required + assert field.getBehaviors().get("t1").required def fieldBehavior = field.behaviors - assert fieldBehavior.get("1").behavior == EDITABLE + assert fieldBehavior.get("t1").behavior == EDITABLE - petriNetService.deletePetriNet(functionTestNet.stringId, userService.getLoggedOrSystem().transformToLoggedUser()) + petriNetService.deleteProcess(new DeleteProcessParams(functionTestNet.stringId)) } @Test void testNamespaceFunctionException() { assertThrows(NullPointerException.class, () -> { - def functionResNet = petriNetService.importPetriNet(functionResNetResource.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() + def functionResNet = petriNetService.importProcess(new ImportProcessParams(functionResNetResource.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert functionResNet def nets = petriNetService.getByIdentifier(FUNCTION_RES_IDENTIFIER) if (nets) { nets.each { - petriNetService.deletePetriNet(it.getStringId(), userService.getLoggedOrSystem().transformToLoggedUser()) + petriNetService.deleteProcess(new DeleteProcessParams(it.getStringId())) } } - def functionTestNet = petriNetService.importPetriNet(functionTestNetResource.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() + def functionTestNet = petriNetService.importProcess(new ImportProcessParams(functionTestNetResource.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert functionTestNet - Case aCase = workflowService.createCase(functionTestNet.stringId, "Test", "", userService.getLoggedOrSystem().transformToLoggedUser()).getCase() - dataService.setData(aCase.getTaskStringId("1"), new DataSet((["number": new NumberField(rawValue: 20d)] as Map>)), superCreator.getLoggedSuper()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(functionTestNet) + .title("Test") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case aCase = workflowService.createCase(createCaseParams).getCase() + dataService.setData(new SetDataParams(aCase.getTaskStringId("t1"), new DataSet((["number": new NumberField(rawValue: 20d)] as Map>)), + superCreator.getLoggedSuper().activeActorId)) }) } @@ -152,52 +182,78 @@ class FunctionsTest { def nets = petriNetService.getByIdentifier(FUNCTION_TEST_IDENTIFIER) if (nets) { nets.each { - petriNetService.deletePetriNet(it.getStringId(), userService.getLoggedOrSystem().transformToLoggedUser()) + petriNetService.deleteProcess(new DeleteProcessParams(it.getStringId())) } } - def functionTestNet = petriNetService.importPetriNet(functionTestNetResource.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() + def functionTestNet = petriNetService.importProcess(new ImportProcessParams(functionTestNetResource.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert functionTestNet - Case aCase = workflowService.createCase(functionTestNet.stringId, "Test", "", userService.getLoggedOrSystem().transformToLoggedUser()).getCase() - dataService.setData(aCase.getTaskStringId("1"), new DataSet((["text": new TextField(rawValue: "20")] as Map>)), superCreator.getLoggedSuper()) - - functionTestNet = petriNetService.importPetriNet(functionTestNetResourceV2.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(functionTestNet) + .title("Test") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case aCase = workflowService.createCase(createCaseParams).getCase() + dataService.setData(new SetDataParams(aCase.getTaskStringId("t1"), new DataSet((["text": new TextField(rawValue: "20")] as Map>)), + superCreator.getLoggedSuper().activeActorId)) + + functionTestNet = petriNetService.importProcess(new ImportProcessParams(functionTestNetResourceV2.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert functionTestNet - dataService.setData(aCase.getTaskStringId("1"), new DataSet((["text": new TextField(rawValue: "20")] as Map>)), superCreator.getLoggedSuper()) + dataService.setData(new SetDataParams(aCase.getTaskStringId("t1"), new DataSet((["text": new TextField(rawValue: "20")] as Map>)), + superCreator.getLoggedSuper().activeActorId)) }) } @Test void testProcessFunctionException() { assertThrows(MissingMethodException.class, () -> { - def functionTestNet = petriNetService.importPetriNet(functionTestNetResource.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() + def functionTestNet = petriNetService.importProcess(new ImportProcessParams(functionTestNetResource.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert functionTestNet - Case aCase = workflowService.createCase(functionTestNet.stringId, "Test", "", userService.getLoggedOrSystem().transformToLoggedUser()).getCase() - dataService.setData(aCase.getTaskStringId("1"), new DataSet((["number3": new NumberField(rawValue: 20d)] as Map>)), superCreator.getLoggedSuper()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(functionTestNet) + .title("Test") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case aCase = workflowService.createCase(createCaseParams).getCase() + dataService.setData(new SetDataParams(aCase.getTaskStringId("t1"), new DataSet((["number3": new NumberField(rawValue: 20d)] as Map>)), + superCreator.getLoggedSuper().activeActorId)) }) } @Test void testNewVersionOfNamespaceFunction() { - def functionResNet = petriNetService.importPetriNet(functionResNetResource.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() - def functionTestNet = petriNetService.importPetriNet(functionTestNetResource.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() + def functionResNet = petriNetService.importProcess(new ImportProcessParams(functionResNetResource.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() + def functionTestNet = petriNetService.importProcess(new ImportProcessParams(functionTestNetResource.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert functionResNet assert functionTestNet - Case aCase = workflowService.createCase(functionTestNet.stringId, "Test", "", userService.getLoggedOrSystem().transformToLoggedUser()).getCase() - dataService.setData(aCase.getTaskStringId("1"), new DataSet((["number": new NumberField(rawValue: 20d)] as Map>)), superCreator.getLoggedSuper()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(functionTestNet) + .title("Test") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case aCase = workflowService.createCase(createCaseParams).getCase() + dataService.setData(new SetDataParams(aCase.getTaskStringId("t1"), new DataSet((["number": new NumberField(rawValue: 20d)] as Map>)), + superCreator.getLoggedSuper().activeActorId)) aCase = workflowService.findOne(aCase.getStringId()) assert aCase.getDataSet().get("number2").rawValue == 20 + 20 - functionResNet = petriNetService.importPetriNet(functionResNetResourceV2.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() + functionResNet = petriNetService.importProcess(new ImportProcessParams(functionResNetResourceV2.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert functionResNet - dataService.setData(aCase.getTaskStringId("1"), new DataSet((["number": new NumberField(rawValue: 20d)] as Map>)), superCreator.getLoggedSuper()) + dataService.setData(new SetDataParams(aCase.getTaskStringId("t1"), new DataSet((["number": new NumberField(rawValue: 20d)] as Map>)), + superCreator.getLoggedSuper().activeActorId)) aCase = workflowService.findOne(aCase.getStringId()) assert aCase.getDataSet().get("number2").rawValue == 20 * 20 @@ -206,17 +262,26 @@ class FunctionsTest { @Test void testNamespaceMethodOverloadingFail() { assertThrows(IllegalArgumentException.class, () -> { - petriNetService.importPetriNet(functionOverloadingFailNetResource.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()) + petriNetService.importProcess(new ImportProcessParams(functionOverloadingFailNetResource.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)) }) } @Test void testNamespaceUseCaseUpdate() { - def functionResV2Net = petriNetService.importPetriNet(functionResNetResourceV2.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() - def functionTestV2Net = petriNetService.importPetriNet(functionTestNetResourceV2.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() - - Case aCase = workflowService.createCase(functionTestV2Net.stringId, "Test", "", userService.getLoggedOrSystem().transformToLoggedUser()).getCase() - dataService.setData(aCase.getTaskStringId("0"), new DataSet((["updateOtherField": new BooleanField(rawValue: true)] as Map>)), superCreator.getLoggedSuper()) + def functionResV2Net = petriNetService.importProcess(new ImportProcessParams(functionResNetResourceV2.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() + def functionTestV2Net = petriNetService.importProcess(new ImportProcessParams(functionTestNetResourceV2.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() + + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(functionTestV2Net) + .title("Test") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case aCase = workflowService.createCase(createCaseParams).getCase() + dataService.setData(new SetDataParams(aCase.getTaskStringId("t0"), new DataSet((["updateOtherField": new BooleanField(rawValue: true)] as Map>)), + superCreator.getLoggedSuper().activeActorId)) aCase = workflowService.findOne(aCase.stringId) assert aCase.getDataSet().get("toBeUpdated").rawValue == 1.0 @@ -231,7 +296,8 @@ class FunctionsTest { @Test void testProcessMethodOverloadingFail() { assertThrows(IllegalArgumentException.class, () -> { - petriNetService.importPetriNet(functionOverloadingFailNetResourceV2.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()) + petriNetService.importProcess(new ImportProcessParams(functionOverloadingFailNetResourceV2.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)) }) } @@ -241,11 +307,18 @@ class FunctionsTest { } private void testMethodOverloading(Resource resource) { - def petriNet = petriNetService.importPetriNet(resource.inputStream, VersionType.MAJOR, userService.getLoggedOrSystem().transformToLoggedUser()).getNet() + def petriNet = petriNetService.importProcess(new ImportProcessParams(resource.inputStream, VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert petriNet - Case aCase = workflowService.createCase(petriNet.stringId, "Test", "", userService.getLoggedOrSystem().transformToLoggedUser()).getCase() - dataService.setData(aCase.getTaskStringId("1"), new DataSet((["number": new NumberField(rawValue: 20d)] as Map>)), superCreator.getLoggedSuper()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(petriNet) + .title("Test") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case aCase = workflowService.createCase(createCaseParams).getCase() + dataService.setData(new SetDataParams(aCase.getTaskStringId("t1"), new DataSet((["number": new NumberField(rawValue: 20d)] as Map>)), + superCreator.getLoggedSuper().activeActorId)) aCase = workflowService.findOne(aCase.getStringId()) NumberField numberField2 = aCase.dataSet.get("number2") as NumberField TextField textField = aCase.dataSet.get("text") as TextField diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ImporterTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ImporterTest.groovy index ea9e4facb1b..846bc283f5c 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ImporterTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ImporterTest.groovy @@ -1,17 +1,20 @@ package com.netgrif.application.engine.petrinet.domain import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.authorization.domain.repositories.RoleRepository import com.netgrif.application.engine.importer.service.Importer import com.netgrif.application.engine.petrinet.domain.dataset.ChoiceField import com.netgrif.application.engine.petrinet.domain.dataset.MultichoiceField import com.netgrif.application.engine.petrinet.domain.dataset.logic.FieldBehavior -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException +import com.netgrif.application.engine.petrinet.domain.version.Version import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.DataFieldBehavior +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import groovy.transform.CompileStatic @@ -27,6 +30,7 @@ import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension import static com.netgrif.application.engine.petrinet.domain.dataset.logic.FieldBehavior.* +import static org.junit.jupiter.api.Assertions.assertThrows @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @@ -41,7 +45,7 @@ class ImporterTest { @Autowired private SuperCreator superCreator @Autowired - private ProcessRoleRepository processRoleRepository + private RoleRepository roleRepository @Autowired private TestHelper testHelper @Autowired @@ -84,34 +88,34 @@ class ImporterTest { @Test void importTest() { - long beforeImportNet = processRoleRepository.count() - def netOptional = petriNetService.importPetriNet( + long beforeImportNet = roleRepository.count() + def netOptional = petriNetService.importProcess(new ImportProcessParams( firstVersionResource.inputStream, VersionType.MAJOR, - superCreator.loggedSuper - ) - assert netOptional.getNet() != null - assert processRoleRepository.count() == beforeImportNet + 2 - long statusImportRole = processRoleRepository.count() - def net = netOptional.getNet() + superCreator.loggedSuper.activeActorId + )) + assert netOptional.getProcess() != null + assert roleRepository.count() == beforeImportNet + 2 + long statusImportRole = roleRepository.count() + def net = netOptional.getProcess() // ASSERT IMPORTED NET assert net.importId == "new_model" assert net.version.major == 1 assert net.version.minor == 0 assert net.version.patch == 0 - assert net.initials == "NEW" + assert net.properties['initials'] == "NEW" assert net.title.defaultValue == "New Model" assert net.icon == "home" - assert net.roles.size() == 2 - 2.times { - assert net.roles.values().toSorted({ a, b -> - return a.importId <=> b.importId - })[it].importId == ("newRole_${it + 1}" as String) - assert net.roles.values().toSorted({ a, b -> - return a.importId <=> b.importId - })[it].name.defaultValue == ("newRole_${it + 1}" as String) - } + // TODO: release/8.0.0 fix +// 2.times { +// assert net.roles.values().toSorted({ a, b -> +// return a.importId <=> b.importId +// })[it].importId == ("newRole_${it + 1}" as String) +// assert net.roles.values().toSorted({ a, b -> +// return a.importId <=> b.importId +// })[it].name.defaultValue == ("newRole_${it + 1}" as String) +// } assert net.dataSet.size() == 5 5.times { assert net.dataSet.values().toSorted({ a, b -> @@ -119,7 +123,7 @@ class ImporterTest { })[it].importId == ("newVariable_${it + 1}" as String) assert net.dataSet.values().toSorted({ a, b -> return a.importId <=> b.importId - })[it].name.defaultValue == ("newVariable_${it + 1}" as String) + })[it].title.defaultValue == ("newVariable_${it + 1}" as String) } assert net.transitions.size() == 3 2.times { @@ -139,18 +143,18 @@ class ImporterTest { assert net.version.major == 1 assert net.version.minor == 0 assert net.version.patch == 0 - assert net.initials == "NEW" + assert net.properties['initials'] == "NEW" assert net.title.defaultValue == "New Model" assert net.icon == "home" - assert net.roles.size() == 2 - 2.times { - assert net.roles.values().toSorted({ a, b -> - return a.importId <=> b.importId - })[it].importId == ("newRole_${it + 1}" as String) - assert net.roles.values().toSorted({ a, b -> - return a.importId <=> b.importId - })[it].name.defaultValue == ("newRole_${it + 1}" as String) - } + // TODO: release/8.0.0 fix +// 2.times { +// assert net.roles.values().toSorted({ a, b -> +// return a.importId <=> b.importId +// })[it].importId == ("newRole_${it + 1}" as String) +// assert net.roles.values().toSorted({ a, b -> +// return a.importId <=> b.importId +// })[it].name.defaultValue == ("newRole_${it + 1}" as String) +// } assert net.dataSet.size() == 5 5.times { assert net.dataSet.values().toSorted({ a, b -> @@ -158,7 +162,7 @@ class ImporterTest { })[it].importId == ("newVariable_${it + 1}" as String) assert net.dataSet.values().toSorted({ a, b -> return a.importId <=> b.importId - })[it].name.defaultValue == ("newVariable_${it + 1}" as String) + })[it].title.defaultValue == ("newVariable_${it + 1}" as String) } assert net.transitions.size() == 3 2.times { @@ -171,27 +175,28 @@ class ImporterTest { } assert net.places.size() == 0 - def netOptional2 = petriNetService.importPetriNet( + def netOptional2 = petriNetService.importProcess(new ImportProcessParams( secondVersionResource.inputStream, VersionType.MAJOR, - superCreator.loggedSuper - ) + superCreator.loggedSuper.activeActorId + )) - assert processRoleRepository.count() == statusImportRole + 1 - assert netOptional2.getNet() != null - def net2 = netOptional2.getNet() + assert roleRepository.count() == statusImportRole + 1 + assert netOptional2.getProcess() != null + def net2 = netOptional2.getProcess() // ASSERT NEW IMPORTED NET assert net2.importId == "new_model" assert net2.version.major == 2 assert net2.version.minor == 0 assert net2.version.patch == 0 - assert net2.initials == "NEW" + assert net2.properties['initials'] == "NEW" assert net2.title.defaultValue == "New Model2" assert net2.icon == "home2" - assert net2.roles.size() == 1 - assert net2.roles.values()[0].importId == "newRole_3" - assert net2.roles.values()[0].name.defaultValue == "newRole_3" + // TODO: release/8.0.0 fix +// assert net2.roles.size() == 1 +// assert net2.roles.values()[0].importId == "newRole_3" +// assert net2.roles.values()[0].name.defaultValue == "newRole_3" assert net2.dataSet.size() == 2 2.times { assert net2.dataSet.values().toSorted({ a, b -> @@ -199,7 +204,7 @@ class ImporterTest { })[it].importId == ("newVariable_${it + 6}" as String) assert net2.dataSet.values().toSorted({ a, b -> return a.importId <=> b.importId - })[it].name.defaultValue == ("newVariable_${it + 6}" as String) + })[it].title.defaultValue == ("newVariable_${it + 6}" as String) } assert net2.transitions.size() == 2 net2.transitions.values()[0].importId == "task3" @@ -213,12 +218,13 @@ class ImporterTest { assert net2.version.major == 2 assert net2.version.minor == 0 assert net2.version.patch == 0 - assert net2.initials == "NEW" + assert net2.properties['initials'] == "NEW" assert net2.title.defaultValue == "New Model2" assert net2.icon == "home2" - assert net2.roles.size() == 1 - assert net2.roles.values()[0].importId == "newRole_3" - assert net2.roles.values()[0].name.defaultValue == "newRole_3" + // TODO: release/8.0.0 fix +// assert net2.roles.size() == 1 +// assert net2.roles.values()[0].importId == "newRole_3" +// assert net2.roles.values()[0].name.defaultValue == "newRole_3" assert net2.dataSet.size() == 2 2.times { assert net2.dataSet.values().toSorted({ a, b -> @@ -226,7 +232,7 @@ class ImporterTest { })[it].importId == ("newVariable_${it + 6}" as String) assert net2.dataSet.values().toSorted({ a, b -> return a.importId <=> b.importId - })[it].name.defaultValue == ("newVariable_${it + 6}" as String) + })[it].title.defaultValue == ("newVariable_${it + 6}" as String) } assert net2.transitions.size() == 2 net2.transitions.values()[0].importId == "task3" @@ -240,18 +246,18 @@ class ImporterTest { assert net.version.major == 1 assert net.version.minor == 0 assert net.version.patch == 0 - assert net.initials == "NEW" + assert net.properties['initials'] == "NEW" assert net.title.defaultValue == "New Model" assert net.icon == "home" - assert net.roles.size() == 2 - 2.times { - assert net.roles.values().toSorted({ a, b -> - return a.importId <=> b.importId - })[it].importId == ("newRole_${it + 1}" as String) - assert net.roles.values().toSorted({ a, b -> - return a.importId <=> b.importId - })[it].name.defaultValue == ("newRole_${it + 1}" as String) - } + // TODO: release/8.0.0 fix +// 2.times { +// assert net.roles.values().toSorted({ a, b -> +// return a.importId <=> b.importId +// })[it].importId == ("newRole_${it + 1}" as String) +// assert net.roles.values(/).toSorted({ a, b -> +// return a.importId <=> b.importId +// })[it].name.defaultValue == ("newRole_${it + 1}" as String) +// } assert net.dataSet.size() == 5 5.times { assert net.dataSet.values().toSorted({ a, b -> @@ -259,7 +265,7 @@ class ImporterTest { })[it].importId == ("newVariable_${it + 1}" as String) assert net.dataSet.values().toSorted({ a, b -> return a.importId <=> b.importId - })[it].name.defaultValue == ("newVariable_${it + 1}" as String) + })[it].title.defaultValue == ("newVariable_${it + 1}" as String) } assert net.transitions.size() == 3 2.times { @@ -275,9 +281,9 @@ class ImporterTest { @Test void upsertTest() { - Optional netOptional = importHelper.upsertNet(FILE_NAME, IDENTIFIER) + Optional netOptional = importHelper.upsertNet(FILE_NAME, IDENTIFIER) assert netOptional.present - PetriNet net = petriNetService.getNewestVersionByIdentifier(IDENTIFIER) + Process net = petriNetService.getNewestVersionByIdentifier(IDENTIFIER) def upserted = importHelper.upsertNet(FILE_NAME, IDENTIFIER) assert upserted.present @@ -287,39 +293,32 @@ class ImporterTest { assert upserted.get().creationDate == net.creationDate } - @Test - void thisKeywordInDataEventsTest() { - PetriNet net = petriNetService.importPetriNet(new ClassPathResource("/this_kw_test.xml").getInputStream(), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet() - - assert net != null - Case testCase = workflowService.createCase(net.stringId, "Test case", "", superCreator.loggedSuper).getCase() - taskService.assignTask(testCase.getTaskStringId("t1")) - testCase = workflowService.findOne(testCase.getStringId()) - assert testCase.getDataSet().get("text_field").getRawValue() == "Hello world!" - assert testCase.getDataSet().get("tester_text_field").getRawValue() == "Hello world!" - } - @Test void initialBehaviorTest() { - PetriNet net = petriNetService.importPetriNet(new ClassPathResource("/initial_behavior.xml").getInputStream(), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet() + Process net = petriNetService.importProcess(new ImportProcessParams(new ClassPathResource("/initial_behavior.xml").getInputStream(), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() assert net - Case testCase = workflowService.createCase(net.stringId, "Test case", "", superCreator.loggedSuper).getCase() - - assertBehaviors(testCase.dataSet.get(NUMBER_FIELD).behaviors.get("1"), FORBIDDEN) - assertBehaviors(testCase.dataSet.get(TEXT_FIELD).behaviors.get("1"), HIDDEN) - assertBehaviors(testCase.dataSet.get(ENUMERATION_FIELD).behaviors.get("1"), VISIBLE) - assertBehaviors(testCase.dataSet.get(ENUMERATION_MAP_FIELD).behaviors.get("1"), EDITABLE) - assertBehaviors(testCase.dataSet.get(MULTICHOICE_FIELD).behaviors.get("1"), EDITABLE, true) - assertBehaviors(testCase.dataSet.get(MULTICHOICE_MAP_FIELD).behaviors.get("1"), EDITABLE, false, true) - assertBehaviors(testCase.dataSet.get(BOOLEAN_FIELD).behaviors.get("1"), EDITABLE) - assertBehaviors(testCase.dataSet.get(DATE_FIELD).behaviors.get("1"), EDITABLE, true) - assertBehaviors(testCase.dataSet.get(DATETIME_FIELD).behaviors.get("1"), EDITABLE, true, true) - assertBehaviors(testCase.dataSet.get(FILE_FIELD).behaviors.get("1"), FORBIDDEN, false, true) - assertBehaviors(testCase.dataSet.get(FILE_LIST_FIELD).behaviors.get("1"), HIDDEN) - assertBehaviors(testCase.dataSet.get(USER_FIELD).behaviors.get("1"), HIDDEN, false, true) - assertBehaviors(testCase.dataSet.get(BUTTON_FIELD).behaviors.get("1"), EDITABLE, true, true) - assertBehaviors(testCase.dataSet.get(I18N_FIELD).behaviors.get("1"), HIDDEN, false, true) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Test case") + .authorId(superCreator.loggedSuper.activeActorId) + .build() + Case testCase = workflowService.createCase(createCaseParams).getCase() + + assertBehaviors(testCase.dataSet.get(NUMBER_FIELD).behaviors.get("t1"), FORBIDDEN) + assertBehaviors(testCase.dataSet.get(TEXT_FIELD).behaviors.get("t1"), HIDDEN) + assertBehaviors(testCase.dataSet.get(ENUMERATION_FIELD).behaviors.get("t1"), VISIBLE) + assertBehaviors(testCase.dataSet.get(ENUMERATION_MAP_FIELD).behaviors.get("t1"), EDITABLE) + assertBehaviors(testCase.dataSet.get(MULTICHOICE_FIELD).behaviors.get("t1"), EDITABLE, true) + assertBehaviors(testCase.dataSet.get(MULTICHOICE_MAP_FIELD).behaviors.get("t1"), EDITABLE, false, true) + assertBehaviors(testCase.dataSet.get(BOOLEAN_FIELD).behaviors.get("t1"), EDITABLE) + assertBehaviors(testCase.dataSet.get(DATE_FIELD).behaviors.get("t1"), EDITABLE, true) + assertBehaviors(testCase.dataSet.get(DATETIME_FIELD).behaviors.get("t1"), EDITABLE, true, true) + assertBehaviors(testCase.dataSet.get(FILE_FIELD).behaviors.get("t1"), FORBIDDEN, false, true) + assertBehaviors(testCase.dataSet.get(FILE_LIST_FIELD).behaviors.get("t1"), HIDDEN) + assertBehaviors(testCase.dataSet.get(USER_FIELD).behaviors.get("t1"), HIDDEN, false, true) + assertBehaviors(testCase.dataSet.get(BUTTON_FIELD).behaviors.get("t1"), EDITABLE, true, true) + assertBehaviors(testCase.dataSet.get(I18N_FIELD).behaviors.get("t1"), HIDDEN, false, true) } @SuppressWarnings('GrMethodMayBeStatic') @@ -331,7 +330,7 @@ class ImporterTest { @Test void enumerationMultichoiceOptionsTest() throws IOException, MissingPetriNetMetaDataException { - PetriNet net = petriNetService.importPetriNet(new ClassPathResource("/enumeration_multichoice_options.xml").getInputStream(), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet() + Process net = petriNetService.importProcess(new ImportProcessParams(new ClassPathResource("/enumeration_multichoice_options.xml").getInputStream(), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() assert net != null @@ -346,37 +345,123 @@ class ImporterTest { assert multichoice.getRawValue() == multichoice_like_map.getRawValue() assert enumeration.getRawValue() == enumeration_like_map.getRawValue() - assert equalSet(multichoice.getDefaultValue(), multichoice_like_map.getDefaultValue()) - assert enumeration.getDefaultValue() == enumeration_like_map.getDefaultValue() + assert enumeration.getDefaultValue().getDefaultValue() == enumeration_like_map.getDefaultValue().getDefaultValue() } @Test - void testDataGroupImportWithoutId() { - def netOutcome = petriNetService.importPetriNet( - new FileInputStream("src/test/resources/datagroup_no_id_test.xml"), - VersionType.MAJOR, - superCreator.loggedSuper) + void createTransitionNoLabel() { + Process net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/NoLabel.xml"), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() + assert net + Process importNet = petriNetService.findByImportId(net.getImportId()).get() + assert importNet + assert importNet.getTransition("t1").getTitle() + assert importNet.getTransition("layout").getTitle() + assert importNet.getTransition("layout").getTitle().defaultValue == "" + } - assert netOutcome.getNet() != null + @Test + void importNetWithParent() { + Process superParentNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/super_parent_to_be_extended.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() + assert superParentNet + + Process parentNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/parent_to_be_extended.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() + assert parentNet.version == new Version(1, 0, 0) + + parentNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/parent_to_be_extended.xml"), + VersionType.MINOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() + assert parentNet.version == new Version(1, 1, 0) + assert parentNet.parentIdentifiers.size() == 1 + + Process childNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/child_extending_parent.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() + assert childNet.identifier == "child_extending_parent" + assert childNet.title.defaultValue == "Child extending parent" + assert childNet.creationDate != parentNet.creationDate + + assert childNet.parentIdentifiers.size() == 2 + assert childNet.parentIdentifiers.get(0).version == superParentNet.version + assert childNet.parentIdentifiers.get(0).identifier == superParentNet.identifier + assert childNet.parentIdentifiers.get(0).id == superParentNet.id + assert childNet.parentIdentifiers.get(1).version == parentNet.version + assert childNet.parentIdentifiers.get(1).identifier == parentNet.identifier + assert childNet.parentIdentifiers.get(1).id == parentNet.id + + assert childNet.places.size() == 3 + assert childNet.places.containsKey("p0") + assert childNet.places.containsKey("p1") + assert childNet.places.containsKey("p2") + + assert childNet.transitions.size() == 4 + assert childNet.transitions.containsKey("t0") + assert childNet.transitions.containsKey("t1") + assert childNet.transitions.containsKey("t2") + // TODO: release/8.0.0 +// assert childNet.transitions.get("t2").dataSet.containsKey("variable1") +// assert childNet.transitions.get("t2").dataSet.get("variable1").field != null + + assert childNet.arcs.size() == 3 + assert childNet.arcs.containsKey("t0") + assert childNet.arcs.get("t0").size() == 2 + assert childNet.arcs.containsKey("t1") + assert childNet.arcs.get("t1").size() == 2 + assert childNet.arcs.containsKey("t2") + assert childNet.arcs.get("t2").size() == 1 + + assert childNet.dataSet.containsKey("variable0") + assert childNet.dataSet.containsKey("variable1") + assert childNet.dataSet.containsKey("variable2") + assert childNet.dataSet.containsKey("taskref2") + // TODO: release/8.0.0 +// assert childNet.dataSet.get("taskref2").defaultValue == ["t0"] +// assert childNet.roles.size() == 3 +// assert childNet.roles.values().find { processRole -> +// processRole.importId == superParentNet.roles.values().first().importId +// } != null + + List properties = ["tag0", "tag1", "tag2"] + assert childNet.properties.size() == properties.size(); + properties.each { property -> + assert childNet.properties.containsKey(property) + } + } - def net = netOutcome.getNet() - net.getTransition("test").getDataGroups().forEach((k, v) -> { - assert v.getStringId() != null && v.getStringId().length() > 0 + @Test + void importNetWithNonExistingParent() { + assertThrows(IllegalArgumentException.class, () -> { + petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/extending_non_existing_parent.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) }) } @Test - void createTransitionNoLabel() { - PetriNet net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/importTest/NoLabel.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet() - assert net - PetriNet importNet = petriNetService.findByImportId(net.getImportId()).get() - assert importNet - assert importNet.getTransition("1").getTitle() - assert importNet.getTransition("layout").getTitle() - assert importNet.getTransition("layout").getTitle().defaultValue == "" + void importNetsWithInvalidExtension() { + Process superParentNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/super_parent_to_be_extended.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() + assert superParentNet + + Process parentNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/parent_to_be_extended.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() + assert parentNet + + assertThrows(IllegalArgumentException.class, () -> { + petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/extending_with_invalid_extension_1.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + }) + + assertThrows(IllegalArgumentException.class, () -> { + petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/extending_with_invalid_extension_2.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + }) + + assertThrows(IllegalArgumentException.class, () -> { + petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/extending_with_invalid_extension_3.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + }) } - private boolean equalSet(Set first, Set second) { + private static boolean equalSet(Set first, Set second) { return first.every { second.any { that -> it.defaultValue == that.defaultValue } } diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/PetriNetTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/PetriNetTest.groovy index 7ffc62b6f05..a506ac750c8 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/PetriNetTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/PetriNetTest.groovy @@ -6,7 +6,8 @@ import com.netgrif.application.engine.petrinet.domain.arcs.Arc import com.netgrif.application.engine.petrinet.domain.arcs.InhibitorArc import com.netgrif.application.engine.petrinet.domain.arcs.ReadArc import com.netgrif.application.engine.petrinet.domain.arcs.ResetArc -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository +import com.netgrif.application.engine.authorization.domain.repositories.ProcessRoleRepository +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference import com.netgrif.application.engine.startup.SuperCreator @@ -25,7 +26,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension @SpringBootTest class PetriNetTest { - public static final String CLONE_NET_TASK = "2" + public static final String CLONE_NET_TRANS_ID = "t2" @Autowired private Importer importer @@ -37,7 +38,7 @@ class PetriNetTest { private SuperCreator superCreator @Autowired - private ProcessRoleRepository processRoleRepository + private ProcessRoleRepository roleRepository @Autowired private TestHelper testHelper @@ -55,16 +56,17 @@ class PetriNetTest { @Test void testClone() { - int beforeImportNet = processRoleRepository.count() + int beforeImportNet = (int) roleRepository.count() - def netOptional = petriNetService.importPetriNet(netResource.inputStream, VersionType.MAJOR, superCreator.loggedSuper) + def netOptional = petriNetService.importProcess(new ImportProcessParams(netResource.inputStream, VersionType.MAJOR, + superCreator.loggedSuper.activeActorId)) - assert netOptional.getNet() != null + assert netOptional.getProcess() != null - def net = netOptional.getNet() + def net = netOptional.getProcess() def clone = net.clone() - def arcs = clone.getArcsOfTransition(CLONE_NET_TASK) + def arcs = clone.getInputArcsOf(CLONE_NET_TRANS_ID) assert arcs.size() == 4 assert arcs.any { it instanceof Arc } @@ -72,25 +74,27 @@ class PetriNetTest { assert arcs.any { it instanceof ResetArc } assert arcs.any { it instanceof ReadArc } - assert net.roles.size() == 2 - assert processRoleRepository.count() == beforeImportNet + 2 + assert roleRepository.count() == beforeImportNet + 2 } @Test void testVersioning() { - def outcome1 = petriNetService.importPetriNet(netResource.inputStream, VersionType.MAJOR, superCreator.loggedSuper) - PetriNet net1 = outcome1.getNet() + def outcome1 = petriNetService.importProcess(new ImportProcessParams(netResource.inputStream, VersionType.MAJOR, + superCreator.loggedSuper.activeActorId)) + Process net1 = outcome1.getProcess() assert net1 - def outcome2 = petriNetService.importPetriNet(netResource.inputStream, VersionType.MAJOR, superCreator.loggedSuper) - PetriNet net2 = outcome2.getNet() + def outcome2 = petriNetService.importProcess(new ImportProcessParams(netResource.inputStream, VersionType.MAJOR, + superCreator.loggedSuper.activeActorId)) + Process net2 = outcome2.getProcess() assert net2 - def outcome3 = petriNetService.importPetriNet(netResource2.inputStream, VersionType.MAJOR, superCreator.loggedSuper) - PetriNet net3 = outcome3.getNet() + def outcome3 = petriNetService.importProcess(new ImportProcessParams(netResource2.inputStream, VersionType.MAJOR, + superCreator.loggedSuper.activeActorId)) + Process net3 = outcome3.getProcess() assert net3 - List nets = petriNetService.getReferencesByVersion(null, superCreator.loggedSuper, Locale.UK) + List nets = petriNetService.getReferencesByVersion(null, Locale.UK) assert nets.findAll { it.identifier in [net1.identifier, net3.identifier] }.size() == 2 assert nets.find { it.identifier == "new_model" }.version == "1.0.0" assert nets.find { it.identifier == "test" }.version == "2.0.0" diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/CaseFieldTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/CaseFieldTest.groovy index 1c02d8ce630..f425ffdaf6d 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/CaseFieldTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/CaseFieldTest.groovy @@ -3,17 +3,17 @@ package com.netgrif.application.engine.petrinet.domain.dataset import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.ipc.TaskApiTest import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import com.netgrif.application.engine.workflow.web.responsebodies.DataSet import groovy.transform.CompileStatic import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired @@ -59,14 +59,15 @@ class CaseFieldTest { @BeforeEach void setup() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void testAllowedNets() { - def testNet = petriNetService.importPetriNet(stream(ALLOWED_NETS_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert testNet.getNet() != null + def testNet = petriNetService.importProcess(new ImportProcessParams(stream(ALLOWED_NETS_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + assert testNet.getProcess() != null - Case aCase = importHelper.createCase("Case 1", testNet.getNet()) + Case aCase = importHelper.createCase("Case 1", testNet.getProcess()) Field field = aCase.getDataSet().get(CASE_FIELD_ID) assert field instanceof CaseField @@ -113,10 +114,10 @@ class CaseFieldTest { @Test void testImmediateAllowedNets() { - def testNet = petriNetService.importPetriNet(stream(ALLOWED_NETS_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert testNet.getNet() != null + def testNet = petriNetService.importProcess(new ImportProcessParams(stream(ALLOWED_NETS_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + assert testNet.getProcess() != null - Case aCase = importHelper.createCase("Case 1", testNet.getNet()) + Case aCase = importHelper.createCase("Case 1", testNet.getProcess()) assert aCase.getImmediateData().size() == 1 CaseField caseRef = (CaseField) aCase.getImmediateData().get(0) @@ -159,13 +160,13 @@ class CaseFieldTest { @Test void testChangeValueAction() { - def notAllowedNet = petriNetService.importPetriNet(stream(ALLOWED_NETS_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert notAllowedNet.getNet() != null + def notAllowedNet = petriNetService.importProcess(new ImportProcessParams(stream(ALLOWED_NETS_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + assert notAllowedNet.getProcess() != null - def testNet = petriNetService.importPetriNet(stream(CHANGE_VALUE_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert testNet.getNet() != null + def testNet = petriNetService.importProcess(new ImportProcessParams(stream(CHANGE_VALUE_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + assert testNet.getProcess() != null - Case aCase = importHelper.createCase("Case 1", testNet.getNet()) + Case aCase = importHelper.createCase("Case 1", testNet.getProcess()) assert aCase.getDataSet().get(CASE_FIELD_ID).rawValue == null diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChangeBehaviorTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChangeBehaviorTest.groovy index 019e46c1bde..bb1c738ae60 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChangeBehaviorTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChangeBehaviorTest.groovy @@ -1,26 +1,20 @@ //file:noinspection GroovyPointlessBoolean package com.netgrif.application.engine.petrinet.domain.dataset +import com.netgrif.application.engine.EngineTest import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.dataset.logic.FieldBehavior -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.startup.SuperCreator +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.QTask import com.netgrif.application.engine.workflow.domain.Task -import com.netgrif.application.engine.workflow.service.interfaces.IDataService -import com.netgrif.application.engine.workflow.service.interfaces.ITaskService -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService +import com.netgrif.application.engine.workflow.domain.params.SetDataParams import com.netgrif.application.engine.workflow.web.responsebodies.DataSet import groovy.transform.CompileStatic import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension @@ -32,64 +26,44 @@ import static com.netgrif.application.engine.petrinet.domain.dataset.logic.Field @ActiveProfiles(["test"]) @SpringBootTest @CompileStatic -class ChangeBehaviorTest { - - @Autowired - private ITaskService taskService - - @Autowired - private IWorkflowService workflowService - - @Autowired - private IDataService dataService - - @Autowired - private ImportHelper helper - - @Autowired - private IPetriNetService petriNetService - - @Autowired - private IUserService userService - - @Autowired - private TestHelper testHelper - - @Autowired - private SuperCreator superCreator - - String TEXT_0_FIELD_ID = "text_0" - String TEXT_1_FIELD_ID = "text_1" - String BOOLEAN_0_FIELD_ID = "boolean_0" - String BOOLEAN_1_FIELD_ID = "boolean_1" - String BOOLEAN_2_FIELD_ID = "boolean_2" - String BOOLEAN_3_FIELD_ID = "boolean_3" - String TEST_CASE_NAME = "Change behavior improvements" - String MAIN_TRANSITION = "t1" - String TEST_TRANSITION_1 = "t3" - String TEST_TRANSITION_2 = "t4" - String TEST_TRANSITION_3 = "t2" - String RESOURCE_PATH = "src/test/resources/change_behavior_update.xml" - - PetriNet net = null +class ChangeBehaviorTest extends EngineTest { + + private String TEXT_0_FIELD_ID = "text_0" + private String TEXT_1_FIELD_ID = "text_1" + private String BOOLEAN_0_FIELD_ID = "boolean_0" + private String BOOLEAN_1_FIELD_ID = "boolean_1" + private String BOOLEAN_2_FIELD_ID = "boolean_2" + private String BOOLEAN_3_FIELD_ID = "boolean_3" + private String TEST_CASE_NAME = "Change behavior improvements" + private String MAIN_TRANSITION = "t1" + private String TEST_TRANSITION_1 = "t3" + private String TEST_TRANSITION_2 = "t4" + private String TEST_TRANSITION_3 = "t2" + private String RESOURCE_PATH = "src/test/resources/change_behavior_update.xml" + + Process net = null @BeforeEach - void initNet() { - testHelper.truncateDbs() - net = petriNetService.importPetriNet(new FileInputStream(RESOURCE_PATH), VersionType.MAJOR, userService.loggedOrSystem.transformToLoggedUser()).getNet() + @Override + void before() { + super.before() + net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream(RESOURCE_PATH), VersionType.MAJOR, + userService.getSystemUser().stringId)).getProcess() assert net != null + + TestHelper.login(superCreator.superIdentity) } @Test void changeBehaviorOfSingleFieldOnSingleTransition() { - Case testCase = helper.createCase(TEST_CASE_NAME, net) + Case testCase = importHelper.createCase(TEST_CASE_NAME, net) Task mainTask = taskService.searchOne(QTask.task.transitionId.eq(MAIN_TRANSITION) & QTask.task.caseId.eq(testCase.stringId)) assert mainTask - dataService.setData(mainTask.stringId, new DataSet([ + dataService.setData(new SetDataParams(mainTask.stringId, new DataSet([ "boolean_0": new BooleanField(rawValue: true) - ] as Map>), superCreator.getLoggedSuper()) + ] as Map>), superCreator.getLoggedSuper().getActiveActorId())) testCase = workflowService.findOne(testCase.getStringId()) assert testCase.dataSet.get(BOOLEAN_0_FIELD_ID).rawValue == true @@ -101,7 +75,7 @@ class ChangeBehaviorTest { @Test void changeBehaviorOnEachTransition() { - Case testCase = helper.createCase(TEST_CASE_NAME, net) + Case testCase = importHelper.createCase(TEST_CASE_NAME, net) Task mainTask = taskService.searchOne(QTask.task.transitionId.eq(MAIN_TRANSITION) & QTask.task.caseId.eq(testCase.stringId)) assert mainTask @@ -110,9 +84,9 @@ class ChangeBehaviorTest { Task otherTask2 = taskService.searchOne(QTask.task.transitionId.eq(TEST_TRANSITION_2) & QTask.task.caseId.eq(testCase.stringId)) assert otherTask2 - dataService.setData(mainTask.stringId, new DataSet([ + dataService.setData(new SetDataParams(mainTask.stringId, new DataSet([ "boolean_1": new BooleanField(rawValue: true) - ] as Map>), superCreator.getLoggedSuper()) + ] as Map>), superCreator.getLoggedSuper().getActiveActorId())) testCase = workflowService.findOne(testCase.getStringId()) assert testCase.dataSet.get(BOOLEAN_1_FIELD_ID).rawValue == true @@ -129,16 +103,16 @@ class ChangeBehaviorTest { @Test void changeBehaviorOfSingleFieldOnMultipleTransitions() { - Case testCase = helper.createCase(TEST_CASE_NAME, net) + Case testCase = importHelper.createCase(TEST_CASE_NAME, net) Task mainTask = taskService.searchOne(QTask.task.transitionId.eq(MAIN_TRANSITION) & QTask.task.caseId.eq(testCase.stringId)) assert mainTask Task otherTask = taskService.searchOne(QTask.task.transitionId.eq(TEST_TRANSITION_1) & QTask.task.caseId.eq(testCase.stringId)) assert otherTask - dataService.setData(mainTask.stringId, new DataSet([ + dataService.setData(new SetDataParams(mainTask.stringId, new DataSet([ "boolean_2": new BooleanField(rawValue: true) - ] as Map>), superCreator.getLoggedSuper()) + ] as Map>), superCreator.getLoggedSuper().getActiveActorId())) testCase = workflowService.findOne(testCase.getStringId()) assert testCase.dataSet.get(BOOLEAN_2_FIELD_ID).rawValue == true @@ -150,16 +124,16 @@ class ChangeBehaviorTest { @Test void changeBehaviorOfMultipleFieldsOnMultipleTransitions() { - Case testCase = helper.createCase(TEST_CASE_NAME, net) + Case testCase = importHelper.createCase(TEST_CASE_NAME, net) Task mainTask = taskService.searchOne(QTask.task.transitionId.eq(MAIN_TRANSITION) & QTask.task.caseId.eq(testCase.stringId)) assert mainTask Task otherTask = taskService.searchOne(QTask.task.transitionId.eq(TEST_TRANSITION_1) & QTask.task.caseId.eq(testCase.stringId)) assert otherTask - dataService.setData(mainTask.stringId, new DataSet([ + dataService.setData(new SetDataParams(mainTask.stringId, new DataSet([ "boolean_3": new BooleanField(rawValue: true) - ] as Map>), superCreator.getLoggedSuper()) + ] as Map>), superCreator.getLoggedSuper().getActiveActorId())) testCase = workflowService.findOne(testCase.getStringId()) assert testCase.dataSet.get(BOOLEAN_3_FIELD_ID).rawValue == true @@ -173,23 +147,23 @@ class ChangeBehaviorTest { @Test void initialBehaviorTest() { - Case testCase = helper.createCase(TEST_CASE_NAME, net) + Case testCase = importHelper.createCase(TEST_CASE_NAME, net) Task mainTask = taskService.searchOne(QTask.task.transitionId.eq(MAIN_TRANSITION) & QTask.task.caseId.eq(testCase.stringId)) assert mainTask - dataService.setData(mainTask.stringId, new DataSet([ + dataService.setData(new SetDataParams(mainTask.stringId, new DataSet([ "boolean_0": new BooleanField(rawValue: true) - ] as Map>), superCreator.getLoggedSuper()) + ] as Map>), superCreator.getLoggedSuper().getActiveActorId())) testCase = workflowService.findOne(testCase.getStringId()) assert testCase.dataSet.get(BOOLEAN_0_FIELD_ID).rawValue == true assert testCase.dataSet.get(TEXT_0_FIELD_ID).behaviors.get(MAIN_TRANSITION).behavior == EDITABLE assert testCase.dataSet.get(TEXT_0_FIELD_ID).behaviors.get(MAIN_TRANSITION).required == true - dataService.setData(mainTask.stringId, new DataSet([ + dataService.setData(new SetDataParams(mainTask.stringId, new DataSet([ "boolean_0": new BooleanField(rawValue: false) - ] as Map>), superCreator.getLoggedSuper()) + ] as Map>), superCreator.getLoggedSuper().getActiveActorId())) testCase = workflowService.findOne(testCase.getStringId()) assert testCase.dataSet.get(BOOLEAN_0_FIELD_ID).rawValue == false diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChangeCasePropertyTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChangeCasePropertyTest.groovy index a8b8ab385c0..e5c437e3b0c 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChangeCasePropertyTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChangeCasePropertyTest.groovy @@ -1,20 +1,24 @@ package com.netgrif.application.engine.petrinet.domain.dataset import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.petrinet.domain.PetriNet + +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.QTask import com.netgrif.application.engine.workflow.domain.Task +import com.netgrif.application.engine.workflow.domain.params.SetDataParams +import com.netgrif.application.engine.workflow.domain.params.TaskParams import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import com.netgrif.application.engine.workflow.web.responsebodies.DataSet import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired @@ -41,9 +45,6 @@ class ChangeCasePropertyTest { @Autowired private IPetriNetService petriNetService - @Autowired - private IUserService userService - @Autowired private TestHelper testHelper @@ -56,17 +57,20 @@ class ChangeCasePropertyTest { String TEST_TRANSITION = "t1" String RESOURCE_PATH = "src/test/resources/case_name_change_test.xml" - PetriNet net = null + Process net = null @BeforeEach void initNet() { testHelper.truncateDbs() - net = petriNetService.importPetriNet(new FileInputStream(RESOURCE_PATH), VersionType.MAJOR, userService.loggedOrSystem.transformToLoggedUser()).getNet() + net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream(RESOURCE_PATH), VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert net != null } @Test + @Disabled("task has no case title attribute") void setTitleFromEvent() { + // todo: release/8.0.0 Case testCase = helper.createCase(TEST_CASE_TITLE, net) assert testCase assert testCase.getTitle() == TEST_CASE_TITLE @@ -74,8 +78,8 @@ class ChangeCasePropertyTest { Task testCaseTask = taskService.searchOne(QTask.task.caseTitle.eq(TEST_CASE_TITLE) & QTask.task.transitionId.eq(TEST_TRANSITION)) assert testCaseTask - taskService.assignTask(testCaseTask.getStringId()) - taskService.finishTask(testCaseTask.getStringId()) + taskService.assignTask(new TaskParams(testCaseTask.getStringId())) + taskService.finishTask(new TaskParams(testCaseTask.getStringId())) testCase = workflowService.findOne(testCase.getStringId()) testCaseTask = taskService.findOne(testCaseTask.getStringId()) @@ -85,7 +89,9 @@ class ChangeCasePropertyTest { } @Test + @Disabled("task has no case title attribute") void setTitleFromFieldAction() { + // todo: release/8.0.0 Case testCase = helper.createCase(TEST_CASE_TITLE, net) assert testCase assert testCase.getTitle() == TEST_CASE_TITLE @@ -93,11 +99,11 @@ class ChangeCasePropertyTest { Task testCaseTask = taskService.searchOne(QTask.task.caseTitle.eq(TEST_CASE_TITLE) & QTask.task.transitionId.eq(TEST_TRANSITION)) assert testCaseTask - taskService.assignTask(testCaseTask.getStringId()) - dataService.setData(testCaseTask.stringId, new DataSet([ + taskService.assignTask(new TaskParams(testCaseTask.getStringId())) + dataService.setData(new SetDataParams(testCaseTask.stringId, new DataSet([ "bln": new BooleanField(rawValue: true) - ] as Map>), superCreator.getSuperUser()) - taskService.finishTask(testCaseTask.getStringId()) + ] as Map>), superCreator.getLoggedSuper().activeActorId)) + taskService.finishTask(new TaskParams(testCaseTask.getStringId())) testCase = workflowService.findOne(testCase.getStringId()) testCaseTask = taskService.findOne(testCaseTask.getStringId()) diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChangeFieldValueInitTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChangeFieldValueInitTest.groovy index c029fddfdee..9dbb7bb9315 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChangeFieldValueInitTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChangeFieldValueInitTest.groovy @@ -2,13 +2,15 @@ package com.netgrif.application.engine.petrinet.domain.dataset import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.QTask import com.netgrif.application.engine.workflow.domain.Task -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.params.TaskParams import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import org.junit.jupiter.api.BeforeEach @@ -45,12 +47,14 @@ class ChangeFieldValueInitTest { @BeforeEach void before() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void testInitValues() { - ImportPetriNetEventOutcome optNet = petriNetService.importPetriNet(new FileInputStream("src/test/resources/petriNets/change_field_value_init.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - Case useCase = importHelper.createCase("test", optNet.getNet()) + // todo: release/8.0.0 field text_static is not injected into expression delegate + ImportPetriNetEventOutcome optNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/petriNets/change_field_value_init.xml"), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + Case useCase = importHelper.createCase("test", optNet.getProcess()) assert useCase.dataSet.get("text_static").rawValue == "TEST VALUE" assert useCase.dataSet.get("text_dynamic").rawValue == "TEST VALUE DYNAMIC" @@ -74,8 +78,8 @@ class ChangeFieldValueInitTest { Case execute(String trans, Case useCase) { Task task = taskService.searchOne(QTask.task.caseId.eq(useCase.getStringId()) & QTask.task.transitionId.eq(trans)) - taskService.assignTask(task.stringId) - taskService.finishTask(task.stringId) + taskService.assignTask(new TaskParams(task.stringId)) + taskService.finishTask(new TaskParams(task.stringId)) return reload(useCase) } diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChoiceFieldTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChoiceFieldTest.groovy index 1027972f9f7..d65c099544e 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChoiceFieldTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ChoiceFieldTest.groovy @@ -6,6 +6,7 @@ import com.netgrif.application.engine.ipc.TaskApiTest import com.netgrif.application.engine.petrinet.domain.DataRef import com.netgrif.application.engine.petrinet.domain.I18nString import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator @@ -41,10 +42,10 @@ class ChoiceFieldTest { private TestHelper testHelper @Autowired - private IPetriNetService petriNetService; + private IPetriNetService petriNetService @Autowired - private SuperCreator superCreator; + private SuperCreator superCreator private Closure stream = { String name -> return TaskApiTest.getClassLoader().getResourceAsStream(name) @@ -53,15 +54,16 @@ class ChoiceFieldTest { @BeforeEach void setup() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void testChoices() { - def netOptional = petriNetService.importPetriNet(stream(LIMITS_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert netOptional.getNet() != null - def net = netOptional.getNet() + def netOptional = petriNetService.importProcess(new ImportProcessParams(stream(LIMITS_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + assert netOptional.getProcess() != null + def net = netOptional.getProcess() - Set choices = ((ChoiceField) net.dataSet["enum"]).choices + Set choices = ((ChoiceField) net.dataSet["enumeration"]).choices assert choices.size() == 3 assert choices.find { it.defaultValue == "Choice 1" } assert choices.find { it.defaultValue == "Choice 2" } @@ -73,7 +75,7 @@ class ChoiceFieldTest { "bool": new BooleanField(rawValue: true) ] as Map>)) List fields = helper.getTaskData(LEASING_NET_TASK_EDIT_COST, choiceCase.stringId) - choices = ((EnumerationField) fields.find { it.field.name.defaultValue == "Enum" }.field).choices + choices = ((EnumerationField) fields.find { it.field.title.defaultValue == "Enum" }.field).choices assert choices.size() == 3 assert choices.find { it.defaultValue == "Choice 1" } @@ -85,7 +87,7 @@ class ChoiceFieldTest { ] as Map>)) fields = helper.getTaskData(LEASING_NET_TASK_EDIT_COST, choiceCase.stringId) - choices = ((EnumerationField) fields.find { it.field.name.defaultValue == "Enum" }.field).choices + choices = ((EnumerationField) fields.find { it.field.title.defaultValue == "Enum" }.field).choices assert choices.size() == 3 assert choices.find { it.defaultValue == "Choice A" } @@ -97,7 +99,7 @@ class ChoiceFieldTest { ] as Map>)) fields = helper.getTaskData(LEASING_NET_TASK_EDIT_COST, choiceCase.stringId) - choices = ((EnumerationField) fields.find { it.field.name.defaultValue == "Enum" }.field).choices + choices = ((EnumerationField) fields.find { it.field.title.defaultValue == "Enum" }.field).choices assert choices.size() == 3 assert choices.find { it.defaultValue == "Choice 1" } diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicCaseNameTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicCaseNameTest.groovy index 01b714e2862..a070a81ecf9 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicCaseNameTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicCaseNameTest.groovy @@ -2,10 +2,12 @@ package com.netgrif.application.engine.petrinet.domain.dataset import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -35,15 +37,27 @@ class DynamicCaseNameTest { @BeforeEach void before() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void testInitValues() { - ImportPetriNetEventOutcome optNet = petriNetService.importPetriNet(new FileInputStream("src/test/resources/petriNets/dynamic_case_name_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - Case useCase = workflowService.createCase(optNet.getNet().stringId, null, "", superCreator.loggedSuper, Locale.forLanguageTag("sk-SK")).getCase() + ImportPetriNetEventOutcome optNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/petriNets/dynamic_case_name_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(optNet.getProcess()) + .authorId(superCreator.loggedSuper.activeActorId) + .locale(Locale.forLanguageTag("sk-SK")) + .build() + Case useCase = workflowService.createCase(createCaseParams).getCase() assert useCase.title == "SK text value 6" - Case useCase2 = workflowService.createCase(optNet.getNet().stringId, null, "", superCreator.loggedSuper, Locale.ENGLISH).getCase() + createCaseParams = CreateCaseParams.with() + .process(optNet.getProcess()) + .authorId(superCreator.loggedSuper.activeActorId) + .locale(Locale.ENGLISH) + .build() + Case useCase2 = workflowService.createCase(createCaseParams).getCase() assert useCase2.title == "EN text value 6" } } diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicChoicesTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicChoicesTest.groovy index 85f56582407..3674a71dca0 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicChoicesTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicChoicesTest.groovy @@ -2,10 +2,11 @@ package com.netgrif.application.engine.petrinet.domain.dataset import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.ITaskService @@ -23,37 +24,40 @@ import org.springframework.test.context.junit.jupiter.SpringExtension class DynamicChoicesTest { @Autowired - private TestHelper testHelper; + private TestHelper testHelper @Autowired private ImportHelper importHelper @Autowired - private IPetriNetService petriNetService; + private IPetriNetService petriNetService @Autowired - private SuperCreator superCreator; + private SuperCreator superCreator @Autowired - private IDataService dataService; + private IDataService dataService @Autowired - private ITaskService taskService; + private ITaskService taskService @Autowired - private CaseRepository caseRepository; + private CaseRepository caseRepository @BeforeEach void before() { - testHelper.truncateDbs(); + testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void testDynamicEnum() { - ImportPetriNetEventOutcome optNet = petriNetService.importPetriNet(new FileInputStream("src/test/resources/petriNets/dynamic_choices.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); + // todo: release/8.0.0 choices does not exist anymore + ImportPetriNetEventOutcome optNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/petriNets/dynamic_choices.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) - assert optNet.getNet() != null; - def net = optNet.getNet() + assert optNet.getProcess() != null + def net = optNet.getProcess() def aCase = importHelper.createCase("Case", net) diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicDefaultValueTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicDefaultValueTest.groovy index 89c02c355dc..1ca78bb0334 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicDefaultValueTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicDefaultValueTest.groovy @@ -2,11 +2,12 @@ package com.netgrif.application.engine.petrinet.domain.dataset import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome import groovy.transform.CompileStatic import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -37,15 +38,17 @@ class DynamicDefaultValueTest { @BeforeEach void before() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void testInitValues() { - ImportPetriNetEventOutcome optNet = petriNetService.importPetriNet(new FileInputStream("src/test/resources/petriNets/dynamic_init.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - Case useCase = importHelper.createCase("test", optNet.getNet()) + ImportPetriNetEventOutcome optNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/petriNets/dynamic_init.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + Case useCase = importHelper.createCase("test", optNet.getProcess()) - assert useCase.dataSet.get("text").rawValue == superCreator.superUser.name - assert useCase.dataSet.get("number").rawValue as Integer == superCreator.superUser.name.length() + assert useCase.dataSet.get("text").rawValue == superCreator.superIdentity.firstname + assert useCase.dataSet.get("number").rawValue as Integer == superCreator.superIdentity.firstname.length() assert useCase.dataSet.get("date").rawValue != null assert useCase.dataSet.get("dateTime").rawValue != null assert (useCase.dataSet.get("user").rawValue as UserFieldValue) != null diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicEnumerationTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicEnumerationTest.groovy index 14fee16971f..60e9c1d229f 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicEnumerationTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicEnumerationTest.groovy @@ -1,23 +1,18 @@ package com.netgrif.application.engine.petrinet.domain.dataset +import com.netgrif.application.engine.EngineTest import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.petrinet.domain.I18nString import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.startup.SuperCreator +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.utils.FullPageRequest import com.netgrif.application.engine.workflow.domain.Task -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome -import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository -import com.netgrif.application.engine.workflow.service.interfaces.IDataService -import com.netgrif.application.engine.workflow.service.interfaces.ITaskService +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.params.SetDataParams import com.netgrif.application.engine.workflow.web.responsebodies.DataSet import groovy.transform.CompileStatic -import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension @@ -28,51 +23,28 @@ import java.util.stream.Collectors @ActiveProfiles(["test"]) @CompileStatic @ExtendWith(SpringExtension.class) -class DynamicEnumerationTest { - - @Autowired - private TestHelper testHelper; - - @Autowired - private ImportHelper importHelper - - @Autowired - private IPetriNetService petriNetService; - - @Autowired - private SuperCreator superCreator; - - @Autowired - private IDataService dataService; - - @Autowired - private ITaskService taskService; - - @Autowired - private CaseRepository caseRepository; - - @BeforeEach - public void before() { - testHelper.truncateDbs(); - } +class DynamicEnumerationTest extends EngineTest { @Test void testDynamicEnum() { - ImportPetriNetEventOutcome optNet = petriNetService.importPetriNet(new FileInputStream("src/test/resources/test_autocomplete_dynamic.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); + TestHelper.login(superCreator.superIdentity) + + ImportPetriNetEventOutcome optNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/test_autocomplete_dynamic.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) - assert optNet.getNet() != null; - def net = optNet.getNet() + assert optNet.getProcess() != null + def net = optNet.getProcess() def aCase = importHelper.createCase("Case", net) assert aCase != null - Task task = taskService.findByCases(new FullPageRequest(), Collections.singletonList(aCase.getStringId())).stream().collect(Collectors.toList()).get(0); + Task task = taskService.findByCases(new FullPageRequest(), Collections.singletonList(aCase.getStringId())).stream().collect(Collectors.toList()).get(0) importHelper.assignTask("Autocomplete", aCase.getStringId(), superCreator.getLoggedSuper()) def dataSet = new DataSet([ "autocomplete": new EnumerationField(rawValue: new I18nString("Case")) ] as Map>) - dataService.setData(task.stringId, dataSet, superCreator.getSuperUser()) + dataService.setData(new SetDataParams(task.stringId, dataSet, superCreator.getLoggedSuper().activeActorId)) def caseOpt = caseRepository.findById(aCase.stringId) assert caseOpt.isPresent() diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicValidationPerformanceTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicValidationPerformanceTest.groovy deleted file mode 100644 index a3992a8c08a..00000000000 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicValidationPerformanceTest.groovy +++ /dev/null @@ -1,100 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.dataset - -import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.startup.SuperCreator -import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.Task -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome -import com.netgrif.application.engine.workflow.service.interfaces.IDataService -import com.netgrif.application.engine.workflow.service.interfaces.ITaskService -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.test.context.ActiveProfiles -import org.springframework.test.context.junit.jupiter.SpringExtension - -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter -import java.time.temporal.ChronoUnit - -@Slf4j -@SpringBootTest -@ActiveProfiles(["test"]) -@CompileStatic -@ExtendWith(SpringExtension.class) -class DynamicValidationPerformanceTest { - - @Autowired - private TestHelper testHelper - - @Autowired - private ImportHelper importHelper - - @Autowired - private IPetriNetService petriNetService - - @Autowired - private SuperCreator superCreator - - @Autowired - private IDataService dataService - - @Autowired - private ITaskService taskService - - @Autowired - private IWorkflowService workflowService - - @BeforeEach - void before() { - testHelper.truncateDbs() - } - - @Test - void testValidations() { - // TODO: release/8.0.0 Object f.text_valid_switch does not exists - ImportPetriNetEventOutcome optNet1 = petriNetService.importPetriNet(new FileInputStream("src/test/resources/petriNets/dynamic_validations_performance_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - ImportPetriNetEventOutcome optNet2 = petriNetService.importPetriNet(new FileInputStream("src/test/resources/petriNets/dynamic_validations_performance_test_comparison.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - - def aCase1 = importHelper.createCase("Case 1", optNet1.getNet()) - def aCase2 = importHelper.createCase("Case 2", optNet2.getNet()) - - run(aCase1, aCase2) - run(aCase1, aCase2) - run(aCase1, aCase2) - run(aCase1, aCase2) - run(aCase1, aCase2) - run(aCase1, aCase2) - } - - Map getData(Case useCase) { - Task task = task(useCase) - return dataService.getData(task, useCase, superCreator.getSuperUser()).getData().collectEntries { [(it.fieldId): (it)] } - } - - Task task(Case useCase) { - return taskService.findOne(useCase.getTaskStringId("transition")) - } - - void run(Case first, Case second) { - LocalDateTime pre1 = LocalDateTime.now() - getData(first) - LocalDateTime post1 = LocalDateTime.now() - - LocalDateTime pre2 = LocalDateTime.now() - getData(second) - LocalDateTime post2 = LocalDateTime.now() - - DateTimeFormatter format = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss.SSS") - log.info("With dynamic validations: ${pre1.format(format)} - ${post1.format(format)} = ${ChronoUnit.MILLIS.between(pre1, post1)}ms") - log.info("With static validations: ${pre2.format(format)} - ${post2.format(format)} = ${ChronoUnit.MILLIS.between(pre2, post2)}ms") - } -} diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicValidationTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicValidationTest.groovy deleted file mode 100644 index 3f2a1f5479c..00000000000 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/DynamicValidationTest.groovy +++ /dev/null @@ -1,121 +0,0 @@ -package com.netgrif.application.engine.petrinet.domain.dataset - -import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.startup.SuperCreator -import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.Task -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome -import com.netgrif.application.engine.workflow.service.interfaces.IDataService -import com.netgrif.application.engine.workflow.service.interfaces.ITaskService -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.test.context.ActiveProfiles -import org.springframework.test.context.junit.jupiter.SpringExtension - -@SpringBootTest -@ActiveProfiles(["test"]) -@ExtendWith(SpringExtension.class) -class DynamicValidationTest { - - @Autowired - private TestHelper testHelper - - @Autowired - private ImportHelper importHelper - - @Autowired - private IPetriNetService petriNetService - - @Autowired - private SuperCreator superCreator - - @Autowired - private IDataService dataService - - @Autowired - private ITaskService taskService - - @Autowired - private IWorkflowService workflowService - - @BeforeEach - void before() { - testHelper.truncateDbs(); - } - -// @Test -// @Disabled -// void testValidations() { -// ImportPetriNetEventOutcome optNet = petriNetService.importPetriNet(new FileInputStream("src/test/resources/petriNets/dynamic_validations.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) -// Case useCase = importHelper.createCase("test", optNet.getNet()) -// Map data = getData(useCase) -// assert (data["number"]).validations[0] instanceof DynamicValidation -// assert (data["number"]).validations[0].compiledRule == ("inrange ${useCase.dataSet["min"].value as Integer},${useCase.dataSet["max"].value as Integer}" as String) -// assert (data["number"]).validations[0].validationMessage.defaultValue == "Number field validation message" -// -// assert (data["text"]).validations[0] instanceof DynamicValidation -// assert (data["text"]).validations[0].compiledRule == ("maxLength ${useCase.dataSet["max"].value as Integer}" as String) -// -// assert (data["date"]).validations[0] instanceof DynamicValidation -// assert (data["date"]).validations[0].compiledRule == ("between past,today-P${useCase.dataSet["max"].value as Integer}D" as String) -// -// SetDataEventOutcome changes = setData(useCase, ["number_valid_switch": ["type": "boolean", "value": true], -// "text_valid_switch" : ["type": "boolean", "value": true]]) -// assert (changes.changedFields["number"].attributes["validations"] as List)[0]["validationRule"] == "odd" -// assert (changes.changedFields["text"].attributes["validations"] as List)[0]["validationRule"] == "email" -// -// useCase = workflowService.findOne(useCase.stringId) -// assert useCase.dataSet["number"].validations[0].validationRule == "odd" -// assert useCase.dataSet["text"].validations[0].validationRule == "email" -// -// data = getData(useCase) -// assert !((data["number"]).validations[0] instanceof DynamicValidation) -// assert (data["number"]).validations[0].validationRule == "odd" -// -// assert !((data["text"]).validations[0] instanceof DynamicValidation) -// assert (data["text"]).validations[0].validationRule == "email" -// -// changes = setData(useCase, ["number_valid_switch": ["type": "boolean", "value": false], -// "text_valid_switch" : ["type": "boolean", "value": false]]) -// assert (changes.changedFields["number"].attributes["validations"] as List)[0]["validationRule"] == ("inrange ${useCase.dataSet["min"].value as Integer},${useCase.dataSet["max"].value as Integer}" as String) -// assert (changes.changedFields["text"].attributes["validations"] as List)[0]["validationRule"] == ("maxLength ${useCase.dataSet["max"].value as Integer}" as String) -// -// setData(useCase, ["min": ["type": "number", "value": "10"], -// "max": ["type": "number", "value": "20"]]) -// -// useCase = workflowService.findOne(useCase.stringId) -// data = getData(useCase) -// assert data["number"].validations[0].compiledRule == ("inrange 10,20" as String) -// assert data["text"].validations[0].compiledRule == ("maxLength 20" as String) -// -// assert useCase.dataSet["number"].validations[0].validationRule == '''inrange ${min.value as Integer},${max.value as Integer}''' -// assert useCase.dataSet["text"].validations[0].validationRule == '''maxLength ${max.value as Integer}''' -// -// assert (useCase.dataSet["number"].validations[0] as DynamicValidation).expression.definition == '''"inrange ${min.value as Integer},${max.value as Integer}"''' -// assert (useCase.dataSet["text"].validations[0] as DynamicValidation).expression.definition == '''"maxLength ${max.value as Integer}"''' -// -// } -// -// Map getData(Case useCase) { -// Task task = task(useCase) -// return dataService.getData(task, useCase).getData().collectEntries { [(it.importId): (it)] } -// } -// -// SetDataEventOutcome setData(Case useCase, Map> values) { -// Task task = task(useCase) -// return dataService.setData(task, ImportHelper.populateDataset(values)) -// } -// -// Task task(Case useCase) { -// return taskService.findOne(useCase.tasks.find { it.transitionId == "transition" }.taskId) -// } -} diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FieldTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FieldTest.groovy index a0d1c0f70da..8df1c757121 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FieldTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FieldTest.groovy @@ -1,11 +1,10 @@ package com.netgrif.application.engine.petrinet.domain.dataset import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.repositories.UserRepository import com.netgrif.application.engine.importer.service.Importer import com.netgrif.application.engine.ipc.TaskApiTest -import com.netgrif.application.engine.petrinet.domain.PetriNet -import com.netgrif.application.engine.startup.GroupRunner +import com.netgrif.application.engine.petrinet.domain.I18nString +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.startup.SystemUserRunner import org.junit.jupiter.api.BeforeEach @@ -33,13 +32,7 @@ class FieldTest { private MongoTemplate template @Autowired - private UserRepository userRepository - - @Autowired - private SystemUserRunner systemUserRunner - - @Autowired - private GroupRunner groupRunner + private SystemUserRunner systemIdentityRunner @Autowired private TestHelper testHelper @@ -51,17 +44,17 @@ class FieldTest { return TaskApiTest.getClassLoader().getResourceAsStream(name) } - def limitsNetOptional - PetriNet net + Process net @BeforeEach void before() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void testImport() { - limitsNetOptional = importer.importPetriNet(stream(LIMITS_NET_FILE)) + net = importer.importPetriNet(stream(LIMITS_NET_FILE)).process assertNet() assertNumberField() @@ -81,40 +74,39 @@ class FieldTest { } private void assertNet() { - assert limitsNetOptional.isPresent() - net = limitsNetOptional.get() + assert net != null assert net.dataSet.size() == 15 } private void assertNumberField() { NumberField field = net.dataSet["number"] as NumberField - assert field.defaultValue == 10.0 + assert field.defaultValue.defaultValue == 10.0 assert field.description.defaultValue == "Number field description" - assert field.name.defaultValue == "Number" + assert field.title.defaultValue == "Number" assert field.placeholder.defaultValue == "Number field placeholder" //TODO: release/8.0.0 validations are ignored // java.lang.NullPointerException: Cannot invoke method get() on null object - assert field.validations.get(0).rule == "inrange 0,inf" - assert field.validations.get(1).rule == "inrange 0,inf" - assert field.validations.get(1).message.defaultValue == "Number field validation message" + assert field.validations.get(0).name == "inrange" + assert field.validations.get(0).serverArguments.argument.get(0).defaultValue == "0" + assert field.validations.get(0).serverArguments.argument.get(1).defaultValue == "inf" + assert field.validations.get(0).message.defaultValue == "Number field validation message" } private void assertTextField() { TextField field = net.dataSet["text"] as TextField - assert field.defaultValue == "text" + assert field.defaultValue.defaultValue == "text" assert field.description.defaultValue == "Text field description" - assert field.name.defaultValue == "Text" + assert field.title.defaultValue == "Text" assert field.placeholder.defaultValue == "Text field placeholder" - assert field.validations.get(0).rule == "email" - assert field.validations.get(1).rule == "email" - assert field.validations.get(1).message.defaultValue == "Mail validation message" + assert field.validations.get(0).name == "email" + assert field.validations.get(0).message.defaultValue == "Mail validation message" } private void assertEnumerationField() { EnumerationField field = net.dataSet["enumeration"] as EnumerationField - assert field.defaultValue == "enumeration" + assert field.defaultValue.defaultValue == new I18nString("enumeration") assert field.description.defaultValue == "Enumeration field description" - assert field.name.defaultValue == "Enumeration" + assert field.title.defaultValue == "Enumeration" assert field.placeholder.defaultValue == "Enumeration field placeholder" assert field.choices.size() == 3 assert field.choices.find { it.defaultValue == "enumeration" } @@ -124,11 +116,11 @@ class FieldTest { private void assertMultichoiceField() { MultichoiceField field = net.dataSet["multichoice"] as MultichoiceField - assert field.defaultValue.size() == 2 - assert field.defaultValue.find { it.defaultValue == "multichoice" } - assert field.defaultValue.find { it.defaultValue == "multichoice2" } + assert field.defaultValue.defaultValue.size() == 2 + assert field.defaultValue.defaultValue.find { it.defaultValue == "multichoice" } + assert field.defaultValue.defaultValue.find { it.defaultValue == "multichoice2" } assert field.description.defaultValue == "Multichoice field description" - assert field.name.defaultValue == "Multichoice" + assert field.title.defaultValue == "Multichoice" assert field.placeholder.defaultValue == "Multichoice field placeholder" assert field.choices.size() == 3 assert field.choices.find { it.defaultValue == "multichoice" } @@ -136,90 +128,99 @@ class FieldTest { assert field.choices.find { it.defaultValue == "multichoice3" } MultichoiceField emptyField = net.dataSet["emptyMultichoice"] as MultichoiceField - assert emptyField.defaultValue instanceof HashSet - assert emptyField.defaultValue.isEmpty() + assert emptyField.defaultValue.defaultValue instanceof HashSet + assert emptyField.defaultValue.defaultValue.isEmpty() } private void assertBooleanField() { BooleanField field = net.dataSet["boolean"] as BooleanField - assert field.defaultValue == true + assert field.defaultValue.defaultValue == true assert field.description.defaultValue == "Boolean field description" - assert field.name.defaultValue == "Boolean" + assert field.title.defaultValue == "Boolean" assert field.placeholder.defaultValue == "Boolean field placeholder" } private void assertDateField() { DateField field = net.dataSet["date"] as DateField assert field.description.defaultValue == "Date field description" - assert field.name.defaultValue == "Date" + assert field.title.defaultValue == "Date" assert field.placeholder.defaultValue == "Date field placeholder" - assert field.validations.get(0).rule == "between today,future" - assert field.validations.get(1).message.defaultValue == "Date field validation message" - assert field.validations.get(1).rule == "between today,future" - assert field.validations.get(2).message.defaultValue == "Date field validation message 2" - assert field.validations.get(2).rule == "between today,tommorow" + assert field.validations.get(0).message.defaultValue == "Date field validation message" + assert field.validations.get(0).name == "between" + assert field.validations.get(0).serverArguments.argument.get(0).defaultValue == "today" + assert field.validations.get(0).serverArguments.argument.get(1).defaultValue == "future" + assert field.validations.get(1).message.defaultValue == "Date field validation message 2" + assert field.validations.get(1).name == "between" + assert field.validations.get(1).serverArguments.argument.get(0).defaultValue == "today" + assert field.validations.get(1).serverArguments.argument.get(1).defaultValue == "tommorow" } private void assertFileField() { FileField field = net.dataSet["file"] as FileField assert field.description.defaultValue == "File field description" - assert field.name.defaultValue == "File" + assert field.title.defaultValue == "File" assert field.placeholder.defaultValue == "File field placeholder" } private void assertUserField() { UserField field = net.dataSet["user"] as UserField assert field.description.defaultValue == "User field description" - assert field.name.defaultValue == "User" + assert field.title.defaultValue == "User" assert field.placeholder.defaultValue == "User field placeholder" } private void assertDateTimeField() { DateTimeField field = net.dataSet["dateTime"] as DateTimeField assert field.description.defaultValue == "DateTime field description" - assert field.name.defaultValue == "DateTime" + assert field.title.defaultValue == "DateTime" assert field.placeholder.defaultValue == "DateTime field placeholder" } private void assertCaseRef() { CaseField field = net.dataSet["caseRef"] as CaseField - assert field.name.defaultValue == "CaseRef" + assert field.title.defaultValue == "CaseRef" assert field.allowedNets.size() == 2 assert field.allowedNets.containsAll(["processId1", "processId2"]) } private void assertUserList() { UserListField field = net.dataSet["emptyUserList"] as UserListField - assert field.name.defaultValue == "Empty user list" + assert field.title.defaultValue == "Empty user list" assert field.description.defaultValue == "User list description" - assert field.defaultValue == null + assert field.defaultValue.defaultValue == null } private void assertTaskRef() { TaskField field = net.dataSet["emptyTaskRef"] as TaskField - assert field.name.defaultValue == "Empty task ref" - assert field.defaultValue instanceof List - assert field.defaultValue.isEmpty() + assert field.title.defaultValue == "Empty task ref" + assert field.defaultValue.defaultValue instanceof List + assert field.defaultValue.defaultValue.isEmpty() } private void assertMultichoiceMap() { MultichoiceMapField field = net.dataSet["emptyMultichoiceMap"] as MultichoiceMapField - assert field.name.defaultValue == "Empty multichoice map" + assert field.title.defaultValue == "Empty multichoice map" assert field.description.defaultValue == "Multichoice map description" assert field.placeholder.defaultValue == "Multichoice map placeholder" - assert field.defaultValue instanceof Set - assert field.defaultValue.isEmpty() + assert field.defaultValue.defaultValue instanceof Set + assert field.defaultValue.defaultValue.isEmpty() } private void assertI18nField() { I18nField field = net.dataSet["i18n"] as I18nField - assert field.name.defaultValue == "Text I18n" + assert field.title.defaultValue == "Text I18n" assert field.description.defaultValue == "This is I18n text field" assert field.placeholder.defaultValue == "Text I18n field" - assert field.defaultValue.defaultValue == "Default i18n text value" - assert field.validations.get(0).rule == "translationRequired sk,en" + assert field.defaultValue.defaultValue.defaultValue == "Default i18n text value" + assert field.validations.get(0).name == "translationRequired" + assert field.validations.get(0).serverArguments.argument.get(0).defaultValue == "sk" + assert field.validations.get(0).serverArguments.argument.get(1).defaultValue == "en" assert field.validations.get(0).message.defaultValue == "Slovak and English language required" - assert field.validations.get(1).rule == "translationOnly sk,en,cz,de" + assert field.validations.get(1).name == "translationOnly" + assert field.validations.get(1).serverArguments.argument.get(0).defaultValue == "sk" + assert field.validations.get(1).serverArguments.argument.get(1).defaultValue == "en" + assert field.validations.get(1).serverArguments.argument.get(2).defaultValue == "cz" + assert field.validations.get(1).serverArguments.argument.get(3).defaultValue == "de" assert field.validations.get(1).message.defaultValue == "Only Slovak, English, Czech and German languages allowed" } } \ No newline at end of file diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileFieldTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileFieldTest.groovy index 633d1f9db26..8a8f063dfc2 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileFieldTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileFieldTest.groovy @@ -2,16 +2,17 @@ package com.netgrif.application.engine.petrinet.domain.dataset import com.netgrif.application.engine.ApplicationEngine import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.IUser -import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService import com.netgrif.application.engine.configuration.properties.SuperAdminConfiguration import com.netgrif.application.engine.importer.service.Importer -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -62,16 +63,16 @@ class FileFieldTest { private IWorkflowService workflowService @Autowired - private IUserService userService + private WebApplicationContext context @Autowired - private WebApplicationContext context + private IPetriNetService petriNetService @Autowired - private IPetriNetService petriNetService; + private SuperCreator superCreator @Autowired - private SuperCreator superCreator; + private IIdentityService identityService private MockMvc mockMvc @@ -84,32 +85,35 @@ class FileFieldTest { .build() } - PetriNet getNet() { - def netOptional = petriNetService.importPetriNet(new FileInputStream("src/test/resources/remoteFileField.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - assert netOptional.getNet() != null - return netOptional.getNet() + Process getNet() { + def netOptional = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/remoteFileField.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) + assert netOptional.getProcess() != null + return netOptional.getProcess() } @Test void testRemoteAttribute() { - PetriNet net = getNet() + Process net = getNet() assert net.getField(FIELD_ID).isPresent() assert (net.getField(FIELD_ID).get() as FileField).isRemote() } @Test void downloadFileByCase() { - PetriNet net = getNet() - - IUser user = userService.findByEmail(configuration.email, true) - assert user != null + Process net = getNet() - Case useCase = workflowService.createCase(net.getStringId(), "Test file download", "black", user.transformToLoggedUser()).getCase() - importHelper.assignTask(TASK_TITLE, useCase.getStringId(), user.transformToLoggedUser()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Test file download") + .authorId(superCreator.loggedSuper.activeActorId) + .build() + Case useCase = workflowService.createCase(createCaseParams).getCase() + importHelper.assignTask(TASK_TITLE, useCase.getStringId(), superCreator.loggedSuper) mockMvc.perform(get("/api/workflow/case/" + useCase.getStringId() + "/file") .param("fieldId", FIELD_ID) - .with(httpBasic(configuration.email, configuration.password))) + .with(httpBasic(superCreator.superIdentity.username, configuration.password))) .andDo(print()) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) @@ -119,17 +123,19 @@ class FileFieldTest { @Test void downloadFileByTask() { - PetriNet net = getNet() - - IUser user = userService.findByEmail(configuration.email, true) - assert user != null + Process net = getNet() - Case useCase = workflowService.createCase(net.getStringId(), "Test file download", "black", user.transformToLoggedUser()).getCase() - importHelper.assignTask(TASK_TITLE, useCase.getStringId(), user.transformToLoggedUser()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Test file download") + .authorId(superCreator.loggedSuper.activeActorId) + .build() + Case useCase = workflowService.createCase(createCaseParams).getCase() + importHelper.assignTask(TASK_TITLE, useCase.getStringId(), superCreator.loggedSuper) mockMvc.perform(get("/api/task/" + importHelper.getTaskId(TASK_TITLE, useCase.getStringId()) + "/file") .param("fieldId", FIELD_ID) - .with(httpBasic(configuration.email, configuration.password))) + .with(httpBasic(superCreator.superIdentity.username, configuration.password))) .andDo(print()) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileListFieldTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileListFieldTest.groovy index ef480bce423..cb1decc9037 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileListFieldTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileListFieldTest.groovy @@ -2,16 +2,18 @@ package com.netgrif.application.engine.petrinet.domain.dataset import com.netgrif.application.engine.ApplicationEngine import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.IUser -import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService import com.netgrif.application.engine.configuration.properties.SuperAdminConfiguration import com.netgrif.application.engine.importer.service.Importer -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -25,7 +27,6 @@ import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.setup.MockMvcBuilders -import org.springframework.util.MultiValueMap import org.springframework.web.context.WebApplicationContext import static org.hamcrest.core.StringContains.containsString @@ -62,15 +63,15 @@ class FileListFieldTest { @Autowired private IWorkflowService workflowService - @Autowired - private IUserService userService - @Autowired private WebApplicationContext context @Autowired private IPetriNetService petriNetService + @Autowired + private IIdentityService identityService + @Autowired private SuperCreator superCreator @@ -85,28 +86,34 @@ class FileListFieldTest { .build() } - PetriNet getNet() { - def netOptional = petriNetService.importPetriNet(new FileInputStream("src/test/resources/remoteFileListField.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert netOptional.getNet() != null - return netOptional.getNet() + Process getNet() { + def netOptional = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/remoteFileListField.xml"), VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)) + assert netOptional.getProcess() != null + return netOptional.getProcess() } @Test void testRemoteAttribute() { - PetriNet net = getNet() + Process net = getNet() assert net.getField(FIELD_ID).isPresent() - assert (net.getField(FIELD_ID).get() as FileListField).isRemote() + assert (net.getField(FIELD_ID).get()).getProperties().get("remote") == "true" } @Test void downloadFileByCaseAndName() { - PetriNet net = getNet() + Process net = getNet() - IUser user = userService.findByEmail(configuration.email, true) - assert user != null + Optional identityOpt = identityService.findByUsername(configuration.email) + assert identityOpt.isPresent() - Case useCase = workflowService.createCase(net.getStringId(), "Test file from file list download", "black", user.transformToLoggedUser()).getCase() - importHelper.assignTask(TASK_TITLE, useCase.getStringId(), user.transformToLoggedUser()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Test file from file list download") + .authorId(identityOpt.get().toSession().activeActorId) + .build() + Case useCase = workflowService.createCase(createCaseParams).getCase() + importHelper.assignTask(TASK_TITLE, useCase.getStringId(), identityOpt.get().toSession()) mockMvc.perform(get("/api/workflow/case/" + useCase.getStringId() + "/file/named") .param("fieldId", FIELD_ID) @@ -121,13 +128,18 @@ class FileListFieldTest { @Test void downloadFileByTask() { - PetriNet net = getNet() + Process net = getNet() - IUser user = userService.findByEmail(configuration.email, true) - assert user != null + Optional identityOpt = identityService.findByUsername(configuration.email) + assert identityOpt.isPresent() - Case useCase = workflowService.createCase(net.getStringId(), "Test file from file list download", "black", user.transformToLoggedUser()).getCase() - importHelper.assignTask(TASK_TITLE, useCase.getStringId(), user.transformToLoggedUser()) + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Test file from file list download") + .authorId(identityOpt.get().toSession().activeActorId) + .build() + Case useCase = workflowService.createCase(createCaseParams).getCase() + importHelper.assignTask(TASK_TITLE, useCase.getStringId(), identityOpt.get().toSession()) // TODO: release/8.0.0 '/test-file-list.txt' or "test-file.txt" ? mockMvc.perform(get("/api/task/" + importHelper.getTaskId(TASK_TITLE, useCase.getStringId()) + "/file/named") diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/MapFieldTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/MapFieldTest.groovy index bd060368d2d..f2a38dfd3bd 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/MapFieldTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/MapFieldTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.petrinet.domain.dataset import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator @@ -41,19 +42,20 @@ class MapFieldTest { @BeforeEach void before() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void testImport() { - def netOptional = petriNetService.importPetriNet(netResource.inputStream, VersionType.MAJOR, superCreator.loggedSuper) - assert netOptional.getNet() != null + def netOptional = petriNetService.importProcess(new ImportProcessParams(netResource.inputStream, VersionType.MAJOR, superCreator.loggedSuper.activeActorId)) + assert netOptional.getProcess() != null - def net = netOptional.getNet() + def net = netOptional.getProcess() assert net.dataSet.size() == 1 EnumerationMapField field = net.dataSet["enumeration"] as EnumerationMapField assert field != null - assert field.name.defaultValue == "Enumeration map" + assert field.title.defaultValue == "Enumeration map" assert field.options.size() == 3 assert field.options["first"].defaultValue == "First option" assert field.options["first"].getTranslation("sk") == "Prvá možnosť" @@ -64,15 +66,15 @@ class MapFieldTest { assert field.options["third"].defaultValue == "Third option" assert field.options["third"].getTranslation("sk") == "Tretia možnosť" assert field.options["third"].getTranslation("de") == "Dritte Option" - assert field.defaultValue == "second" + assert field.defaultValue.defaultValue == "second" } @Test void testValue() { - def netOptional = petriNetService.importPetriNet(netResource.inputStream, VersionType.MAJOR, superCreator.loggedSuper) - assert netOptional.getNet() != null + def netOptional = petriNetService.importProcess(new ImportProcessParams(netResource.inputStream, VersionType.MAJOR, superCreator.loggedSuper.activeActorId)) + assert netOptional.getProcess() != null - Case aCase = importHelper.createCase("Case", netOptional.getNet()) + Case aCase = importHelper.createCase("Case", netOptional.getProcess()) assert aCase.dataSet.get("enumeration") != null assert aCase.dataSet.get("enumeration").rawValue == "second" @@ -106,14 +108,14 @@ class MapFieldTest { @Test void testImportMultichoice() { - def netOptional = petriNetService.importPetriNet(netResource2.inputStream, VersionType.MAJOR, superCreator.loggedSuper) - assert netOptional.getNet() != null + def netOptional = petriNetService.importProcess(new ImportProcessParams(netResource2.inputStream, VersionType.MAJOR, superCreator.loggedSuper.activeActorId)) + assert netOptional.getProcess() != null - def net = netOptional.getNet() + def net = netOptional.getProcess() assert net.dataSet.size() == 1 MultichoiceMapField field = net.dataSet.get("multichoice") as MultichoiceMapField - assert field.name.defaultValue == "Multichoice map" + assert field.title.defaultValue == "Multichoice map" assert field.options.size() == 3 assert field.options["first"].defaultValue == "First option" assert field.options["first"].getTranslation("sk") == "Prvá možnosť" @@ -124,16 +126,17 @@ class MapFieldTest { assert field.options["third"].defaultValue == "Third option" assert field.options["third"].getTranslation("sk") == "Tretia možnosť" assert field.options["third"].getTranslation("de") == "Dritte Option" - assert field.defaultValue.contains("second") - assert field.defaultValue.contains("first") + // TODO: release/8.0.0 +// assert field.defaultValue.contains("second") +// assert field.defaultValue.contains("first") } @Test void testValueMultichoice() { - def netOptional = petriNetService.importPetriNet(netResource2.inputStream, VersionType.MAJOR, superCreator.loggedSuper) - assert netOptional.getNet() != null + def netOptional = petriNetService.importProcess(new ImportProcessParams(netResource2.inputStream, VersionType.MAJOR, superCreator.loggedSuper.activeActorId)) + assert netOptional.getProcess() != null - Case aCase = importHelper.createCase("Case", netOptional.getNet()) + Case aCase = importHelper.createCase("Case", netOptional.getProcess()) MultichoiceMapField multichoiceMapField = aCase.dataSet.get("multichoice") as MultichoiceMapField assert multichoiceMapField != null assert multichoiceMapField.rawValue.size() == 2 diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy index c7aea8a9d98..c9a11d766da 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy @@ -1,11 +1,13 @@ package com.netgrif.application.engine.petrinet.domain.roles import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authorization.domain.ProcessRole +import com.netgrif.application.engine.authorization.domain.repositories.ProcessRoleRepository import com.netgrif.application.engine.importer.service.Importer import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator @@ -48,9 +50,9 @@ class ProcessRoleTest { private static final String CASE_NAME = "Test case" private static final String CASE_INITIALS = "TC" - private static final String USER_EMAIL_VIEW = "ProcessRoleTest@test.com" - private static final String USER_EMAIL_PERFORM = "ProcessRoleTestPerform@test.com" - private static final String USER_EMAIL_BOTH = "ProcessRoleTestPerformView@test.com" + private static final String USER_EMAIL_VIEW = "RoleTest@test.com" + private static final String USER_EMAIL_PERFORM = "RoleTestPerform@test.com" + private static final String USER_EMAIL_BOTH = "RoleTestPerformView@test.com" private Authentication auth @@ -69,7 +71,7 @@ class ProcessRoleTest { private IPetriNetService petriNetService; @Autowired - private ProcessRoleRepository userProcessRoleRepository + private ProcessRoleRepository userRoleRepository @Autowired private SuperCreator superCreator; @@ -86,29 +88,33 @@ class ProcessRoleTest { .apply(springSecurity()) .build() - def net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/rolref_view.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null - - String netId = net.getNet().getStringId() - - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - def processRoles = userProcessRoleRepository.findAllByNetId(netId) - importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL_VIEW, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], - [processRoles.find { - it.getStringId() == net.getNet().roles.values().find { - it.name.defaultValue == "View" - }.stringId - }] as ProcessRole[]) - - importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL_PERFORM, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], - [processRoles.find { it.getStringId() == net.getNet().roles.values().find { it.name.defaultValue == "Perform" }.stringId }] as ProcessRole[]) - - importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL_BOTH, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], - [processRoles.find { it.getStringId() == net.getNet().roles.values().find { it.name.defaultValue == "View" }.stringId }, - processRoles.find { it.getStringId() == net.getNet().roles.values().find { it.name.defaultValue == "Perform" }.stringId }] as ProcessRole[]) + def net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/rolref_view.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) + assert net.getProcess() != null + + ProcessRole viewRole = userRoleRepository.findByImportId("role1") + ProcessRole performRole = userRoleRepository.findByImportId("role2") + + importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Test")) + .lastname(new TextField("Integration")) + .username(new TextField(USER_EMAIL_VIEW)) + .password(new TextField("password")) + .build(), List.of(viewRole)) + + importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Test")) + .lastname(new TextField("Integration")) + .username(new TextField(USER_EMAIL_PERFORM)) + .password(new TextField("password")) + .build(), List.of(performRole)) + + importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Test")) + .lastname(new TextField("Integration")) + .username(new TextField(USER_EMAIL_BOTH)) + .password(new TextField("password")) + .build(), List.of(viewRole, performRole)) } private String caseId diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy index 5c7d20bfe17..46bdea1933c 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy @@ -1,19 +1,18 @@ package com.netgrif.application.engine.petrinet.service import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authorization.domain.Role import com.netgrif.application.engine.configuration.properties.CacheProperties import com.netgrif.application.engine.ipc.TaskApiTest -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -43,9 +42,6 @@ class CachePetriNetServiceTest { @Autowired private IPetriNetService petriNetService - @Autowired - private IUserService userService - @Autowired private CacheManager cacheManager @@ -59,21 +55,23 @@ class CachePetriNetServiceTest { @BeforeEach void setup() { testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - importHelper.createUser(new User(name: "Customer", surname: "User", email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], - [] as ProcessRole[]) + importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Customer")) + .lastname(new TextField("Identity")) + .username(new TextField(CUSTOMER_USER_MAIL)) + .password(new TextField("password")) + .build(), new ArrayList()) } @Test void cacheTest() { assert cacheManager.getCache(cacheProperties.getPetriNetNewest()).get("processDeleteTest") == null - ImportPetriNetEventOutcome testNetOptional = petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert testNetOptional.getNet() != null - PetriNet testNet = testNetOptional.getNet() + ImportPetriNetEventOutcome testNetOptional = petriNetService.importProcess(new ImportProcessParams(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) + assert testNetOptional.getProcess() != null + Process testNet = testNetOptional.getProcess() assert cacheManager.getCache(cacheProperties.getPetriNetNewest()).get(testNet.getIdentifier()) == null - PetriNet test = petriNetService.getNewestVersionByIdentifier(testNet.getIdentifier()) + Process test = petriNetService.getNewestVersionByIdentifier(testNet.getIdentifier()) assert cacheManager.getCache(cacheProperties.getPetriNetNewest()).get(testNet.getIdentifier()).get().equals(test) } } diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy index 3e241f6de76..4a5052b9bae 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy @@ -1,24 +1,28 @@ package com.netgrif.application.engine.petrinet.service import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Author -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authorization.domain.User +import com.netgrif.application.engine.authorization.domain.repositories.ProcessRoleRepository +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService +import com.netgrif.application.engine.authorization.service.interfaces.IUserService import com.netgrif.application.engine.elastic.domain.ElasticPetriNet -import com.netgrif.application.engine.elastic.domain.ElasticPetriNetRepository +import com.netgrif.application.engine.elastic.domain.repoitories.ElasticPetriNetRepository import com.netgrif.application.engine.ipc.TaskApiTest import com.netgrif.application.engine.petrinet.domain.* +import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import com.netgrif.application.engine.petrinet.domain.params.DeleteProcessParams +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository import com.netgrif.application.engine.petrinet.domain.version.Version import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.workflow.domain.Case +import com.netgrif.application.engine.workflow.domain.QCase +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import com.netgrif.application.engine.workflow.domain.repositories.TaskRepository import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService @@ -33,6 +37,8 @@ import org.springframework.data.domain.PageRequest import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension +import static org.junit.jupiter.api.Assertions.assertThrows + @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @SpringBootTest @@ -40,6 +46,9 @@ class PetriNetServiceTest { public static final String NET_FILE = "process_delete_test.xml" public static final String NET_SEARCH_FILE = "process_search_test.xml" + public static final String NET_IMPORT_FILE = "net_import_1.xml" + public static final String PETRINET_IMPORT_FAILURE_FILE = "petriNet_import_failure.xml" + public static final String PETRINET_IMPORT_FAILURE_IDENTIFIER = "petriNet_import_failure" public static final String CUSTOMER_USER_MAIL = "customer@netgrif.com" @Autowired @@ -61,10 +70,7 @@ class PetriNetServiceTest { private TaskRepository taskRepository @Autowired - private IProcessRoleService userProcessRoleService - - @Autowired - private IUserService userService + private IRoleService roleService @Autowired private PetriNetRepository petriNetRepository @@ -76,11 +82,19 @@ class PetriNetServiceTest { private CaseRepository caseRepository @Autowired - private ProcessRoleRepository processRoleRepository + private IIdentityService identityService + + @Autowired + private IUserService userService + + @Autowired + private ProcessRoleRepository roleRepository @Autowired private ElasticPetriNetRepository elasticPetriNetRepository + private Identity testIdentity + private static InputStream stream(String name) { return TaskApiTest.getClassLoader().getResourceAsStream(name) @@ -89,53 +103,55 @@ class PetriNetServiceTest { @BeforeEach void setup() { testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - importHelper.createUser(new User(name: "Customer", surname: "User", email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], - [] as ProcessRole[]) + testIdentity = identityService.createWithDefaultUser(IdentityParams.with() + .username(new TextField(CUSTOMER_USER_MAIL)) + .password(new TextField("password")) + .firstname(new TextField("Customer")) + .lastname(new TextField("Identity")) + .build()) } @Test void processImportAndDelete() { - long processRoleCount = processRoleRepository.count() + long roleCount = roleRepository.count() long processCount = petriNetRepository.count() long taskCount = taskRepository.count() - ImportPetriNetEventOutcome testNetOptional = petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert testNetOptional.getNet() != null + ImportPetriNetEventOutcome testNetOptional = petriNetService.importProcess(new ImportProcessParams(stream(NET_FILE), VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)) + assert testNetOptional.getProcess() != null assert petriNetRepository.count() == processCount + 1 - PetriNet testNet = testNetOptional.getNet() + Process testNet = testNetOptional.getProcess() Thread.sleep(5000) ElasticPetriNet elasticTestNet = elasticPetriNetRepository.findByStringId(testNet.stringId) assert elasticTestNet != null && elasticTestNet.getUriNodeId() == uriService.getRoot().id.toString() assert testNet.getUriNodeId() == uriService.getRoot().id.toString() assert petriNetRepository.findById(testNet.stringId).get().uriNodeId != null + TestHelper.login(superCreator.getSuperIdentity()) importHelper.createCase("Case 1", testNet) assert caseRepository.findAllByProcessIdentifier(testNet.getImportId()).size() == 1 assert taskRepository.count() == taskCount + 3 - assert processRoleRepository.count() == processRoleCount + 2 + assert roleRepository.count() == roleCount + 2 - def user = userService.findByEmail(CUSTOMER_USER_MAIL, false) - assert user != null - assert user.processRoles.size() == 1 + // todo: release/8.0.0 +// assert user.roles.size() == 1 - userService.addRole(user, testNet.roles.values().collect().get(0).stringId) - user = userService.findByEmail(CUSTOMER_USER_MAIL, false) - assert user != null - assert user.processRoles.size() == 2 +// userService.addRole(user, testNet.roles.values().collect().get(0).stringId) +// user = userService.findByEmail(CUSTOMER_USER_MAIL) +// assert user != null +// assert user.roles.size() == 2 assert petriNetService.get(new ObjectId(testNet.stringId)) != null - petriNetService.deletePetriNet(testNet.stringId, superCreator.getLoggedSuper()) + petriNetService.deleteProcess(new DeleteProcessParams(testNet.stringId)) assert petriNetRepository.count() == processCount Thread.sleep(5000) assert elasticPetriNetRepository.findByStringId(testNet.stringId) == null - assert caseRepository.findAllByProcessIdentifier(testNetOptional.getNet().getImportId()).size() == 0 + assert caseRepository.findAllByProcessIdentifier(testNet.getImportId()).size() == 0 assert taskRepository.count() == taskCount - assert processRoleRepository.count() == processRoleCount - user = userService.findByEmail(CUSTOMER_USER_MAIL, false) - assert user != null - assert user.processRoles.size() == 1 +// user = userService.findByEmail(CUSTOMER_USER_MAIL) +// assert user != null +// assert user.roles.size() == 1 boolean exceptionThrown = false try { @@ -150,62 +166,60 @@ class PetriNetServiceTest { @Test void findAllByUriNodeIdTest() { UriNode myNode = uriService.getOrCreate("/test", UriContentType.DEFAULT) - petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper(), myNode.id.toString()) - petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper(), myNode.id.toString()) + petriNetService.importProcess(new ImportProcessParams(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId, + myNode.id.toString())) + petriNetService.importProcess(new ImportProcessParams(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId, + myNode.id.toString())) Thread.sleep(2000) - List petriNets = petriNetService.findAllByUriNodeId(myNode.id.toString()) + List petriNets = petriNetService.findAllByUriNodeId(myNode.id.toString()) assert petriNets.size() == 2 } @Test void processSearch() { - long processCount = petriNetRepository.count() + int processCount = (int) petriNetRepository.count() - def user = userService.findByEmail(CUSTOMER_USER_MAIL, false) - assert user != null - petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - petriNetService.importPetriNet(stream(NET_SEARCH_FILE), VersionType.MAJOR, user.transformToLoggedUser()) + petriNetService.importProcess(new ImportProcessParams(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) + petriNetService.importProcess(new ImportProcessParams(stream(NET_SEARCH_FILE), VersionType.MAJOR, testIdentity.toSession().activeActorId)) assert petriNetRepository.count() == processCount + 2 PetriNetSearch search = new PetriNetSearch() - assert petriNetService.search(search, superCreator.getLoggedSuper(), PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == processCount + 2 + assert petriNetService.search(search, PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == processCount + 2 PetriNetSearch search1 = new PetriNetSearch() search1.setIdentifier("processSearchTest") - assert petriNetService.search(search1, superCreator.getLoggedSuper(), PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 + assert petriNetService.search(search1, PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 PetriNetSearch search2 = new PetriNetSearch() search2.setTitle("Process Search Test") - assert petriNetService.search(search2, superCreator.getLoggedSuper(), PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 + assert petriNetService.search(search2, PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 PetriNetSearch search3 = new PetriNetSearch() search3.setDefaultCaseName("Process Search Case Name") - assert petriNetService.search(search3, superCreator.getLoggedSuper(), PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 + assert petriNetService.search(search3, PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 PetriNetSearch search4 = new PetriNetSearch() search4.setInitials("PST") - assert petriNetService.search(search4, superCreator.getLoggedSuper(), PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 - + assert petriNetService.search(search4, PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 PetriNetSearch search5 = new PetriNetSearch() - Author author = new Author() - author.setEmail(user.getEmail()) - search5.setAuthor(author) - assert petriNetService.search(search5, superCreator.getLoggedSuper(), PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 - + Optional userOpt = userService.findById(testIdentity.toSession().activeActorId) + assert userOpt.isPresent() + search5.setAuthor(userOpt.get()) + assert petriNetService.search(search5, PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 PetriNetSearch search6 = new PetriNetSearch() search6.setVersion(new Version(1, 0, 0)) - assert petriNetService.search(search6, superCreator.getLoggedSuper(), PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == processCount + 2 + assert petriNetService.search(search6, PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == processCount + 2 PetriNetSearch search7 = new PetriNetSearch() HashMap map = new HashMap() map.put("test", "test") search7.setTags(map) - assert petriNetService.search(search7, superCreator.getLoggedSuper(), PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 + assert petriNetService.search(search7, PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 PetriNetSearch search8 = new PetriNetSearch() HashMap mapTags = new HashMap() @@ -215,7 +229,92 @@ class PetriNetServiceTest { search8.setTitle("Process Search Test") search8.setDefaultCaseName("Process Search Case Name") search8.setInitials("PST") - search8.setAuthor(author) - assert petriNetService.search(search8, superCreator.getLoggedSuper(), PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 + search8.setAuthor(userOpt.get()) + assert petriNetService.search(search8, PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1 + } + + @Test + void deleteParentPetriNet() { + Process superParentNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/super_parent_to_be_extended.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)).getProcess() + Case superParentCase = importHelper.createCaseAsSuper("Super parent case", superParentNet) + + Process parentNetMajor = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/parent_to_be_extended.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)).getProcess() + Case parentMajorCase = importHelper.createCaseAsSuper("Parent major case", parentNetMajor) + + Process parentNetMinor = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/parent_to_be_extended.xml"), + VersionType.MINOR, superCreator.getLoggedSuper().activeActorId)).getProcess() + Case parentMinorCase = importHelper.createCaseAsSuper("Parent minor case", parentNetMinor) + + Process childNet = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/importTest/child_extending_parent.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)).getProcess() + Case parentChildCase = importHelper.createCaseAsSuper("Child case", childNet) + + TestHelper.login(superCreator.getSuperIdentity()) + + petriNetService.deleteProcess(new DeleteProcessParams(parentNetMajor.stringId)) + assert petriNetRepository.findById(superParentNet.stringId).isPresent() + assert petriNetRepository.findById(parentNetMajor.stringId).isEmpty() + assert petriNetRepository.findById(parentNetMinor.stringId).isPresent() + assert petriNetRepository.findById(childNet.stringId).isPresent() + assert caseRepository.findById(superParentCase.stringId).isPresent() + assert caseRepository.findById(parentMajorCase.stringId).isEmpty() + assert caseRepository.findById(parentMinorCase.stringId).isPresent() + assert caseRepository.findById(parentChildCase.stringId).isPresent() + + petriNetService.deleteProcess(new DeleteProcessParams(parentNetMinor.stringId)) + assert petriNetRepository.findById(superParentNet.stringId).isPresent() + assert petriNetRepository.findById(parentNetMinor.stringId).isEmpty() + assert petriNetRepository.findById(childNet.stringId).isEmpty() + assert caseRepository.findById(superParentCase.stringId).isPresent() + assert caseRepository.findById(parentMinorCase.stringId).isEmpty() + assert caseRepository.findById(parentChildCase.stringId).isEmpty() + + petriNetService.deleteProcess(new DeleteProcessParams(superParentNet.stringId)) + assert petriNetRepository.findById(superParentNet.stringId).isEmpty() + assert caseRepository.findById(superParentCase.stringId).isEmpty() + } + + @Test + void testTransactionalImportFailure() { + TestHelper.login(superCreator.superIdentity) + + petriNetService.importProcess(new ImportProcessParams(stream(NET_IMPORT_FILE), VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)) + + ImportProcessParams importProcessParams = ImportProcessParams.with() + .isTransactional(true) + .xmlFile(stream(PETRINET_IMPORT_FAILURE_FILE)) + .releaseType(VersionType.MAJOR) + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + + assertThrows(RuntimeException.class, { petriNetService.importProcess(importProcessParams) }) + + assert petriNetService.findByImportId(PETRINET_IMPORT_FAILURE_IDENTIFIER).isEmpty() + assert workflowService.searchOne(QCase.case$.title.eq("CaseFromPre")) == null + assert workflowService.searchOne(QCase.case$.title.eq("CaseFromPost")) == null + } + + @Test + void testNonTransactionalImportFailure() { + TestHelper.login(superCreator.superIdentity) + + petriNetService.importProcess(new ImportProcessParams(stream(NET_IMPORT_FILE), VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)) + + ImportProcessParams importProcessParams = ImportProcessParams.with() + .isTransactional(false) + .xmlFile(stream(PETRINET_IMPORT_FAILURE_FILE)) + .releaseType(VersionType.MAJOR) + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + + assertThrows(RuntimeException.class, { petriNetService.importProcess(importProcessParams) }) + + assert petriNetService.findByImportId(PETRINET_IMPORT_FAILURE_IDENTIFIER).isPresent() + assert workflowService.searchOne(QCase.case$.title.eq("CaseFromPre")) != null + assert workflowService.searchOne(QCase.case$.title.eq("CaseFromPost")) != null } } diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/service/UriServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/service/UriServiceTest.groovy index d6c57f5f550..2d9be76c49a 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/service/UriServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/service/UriServiceTest.groovy @@ -4,10 +4,9 @@ import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.configuration.properties.UriProperties import com.netgrif.application.engine.petrinet.domain.UriContentType import com.netgrif.application.engine.petrinet.domain.UriNode -import com.netgrif.application.engine.petrinet.domain.repository.UriNodeRepository +import com.netgrif.application.engine.petrinet.domain.repositories.UriNodeRepository import com.netgrif.application.engine.petrinet.service.interfaces.IUriService import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy index 177252290f8..bdc15cb8c9d 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy @@ -1,14 +1,17 @@ -package com.netgrif.application.engine.petrinet.webprocessRolesAndPermissionses +package com.netgrif.application.engine.petrinet.web import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authorization.domain.ApplicationRole +import com.netgrif.application.engine.authorization.domain.Role import com.netgrif.application.engine.ipc.TaskApiTest -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService +import com.netgrif.application.engine.startup.ApplicationRoleRunner import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import org.junit.jupiter.api.BeforeEach @@ -63,7 +66,10 @@ class PetriNetControllerTest { @Autowired private TestHelper testHelper - private PetriNet net + @Autowired + private ApplicationRoleRunner applicationRoleRunner + + private Process net private Authentication userAuth private Authentication adminAuth @@ -76,32 +82,36 @@ class PetriNetControllerTest { void before() { testHelper.truncateDbs() - def net = petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null + def net = petriNetService.importProcess(new ImportProcessParams(stream(NET_FILE), VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)) + assert net.getProcess() != null - this.net = net.getNet() + this.net = net.getProcess() mvc = MockMvcBuilders .webAppContextSetup(wac) .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - - importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], -// [] as Group[], - [] as ProcessRole[]) + Identity identity = importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Role")) + .lastname(new TextField("Identity")) + .username(new TextField(USER_EMAIL)) + .password(new TextField("password")) + .build(), new ArrayList()) - userAuth = new UsernamePasswordAuthenticationToken(USER_EMAIL, "password") + userAuth = new UsernamePasswordAuthenticationToken(identity.toSession(), "password") userAuth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) - importHelper.createUser(new User(name: "Admin", surname: "User", email: ADMIN_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("admin")] as Authority[], -// [] as Group[], - [] as ProcessRole[]) + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE) + Identity adminIdentity = importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Admin")) + .lastname(new TextField("Identity")) + .username(new TextField(ADMIN_EMAIL)) + .password(new TextField("password")) + .build(), List.of(adminAppRole)) - adminAuth = new UsernamePasswordAuthenticationToken(ADMIN_EMAIL, "password") + adminAuth = new UsernamePasswordAuthenticationToken(adminIdentity.toSession(), "password") adminAuth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) } diff --git a/src/test/groovy/com/netgrif/application/engine/transaction/TransactionTest.groovy b/src/test/groovy/com/netgrif/application/engine/transaction/TransactionTest.groovy new file mode 100644 index 00000000000..74e5f872754 --- /dev/null +++ b/src/test/groovy/com/netgrif/application/engine/transaction/TransactionTest.groovy @@ -0,0 +1,514 @@ +package com.netgrif.application.engine.transaction + +import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService +import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetService +import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService +import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest +import com.netgrif.application.engine.elastic.web.requestbodies.ElasticTaskSearchRequest +import com.netgrif.application.engine.petrinet.domain.Process +import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.dataset.ButtonField +import com.netgrif.application.engine.petrinet.domain.dataset.Field +import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams +import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService +import com.netgrif.application.engine.startup.ImportHelper +import com.netgrif.application.engine.startup.SuperCreator +import com.netgrif.application.engine.workflow.domain.Case +import com.netgrif.application.engine.workflow.domain.QCase +import com.netgrif.application.engine.workflow.domain.QTask +import com.netgrif.application.engine.workflow.domain.Task +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CreateCaseEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.response.EventOutcomeWithMessage +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.AssignTaskEventOutcome +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.taskoutcomes.FinishTaskEventOutcome +import com.netgrif.application.engine.workflow.domain.params.SetDataParams +import com.netgrif.application.engine.workflow.domain.repositories.TaskRepository +import com.netgrif.application.engine.workflow.service.interfaces.IDataService +import com.netgrif.application.engine.workflow.service.interfaces.ITaskService +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService +import com.netgrif.application.engine.workflow.web.responsebodies.DataSet +import com.netgrif.application.engine.workflow.web.responsebodies.TaskDataSets +import groovy.json.JsonOutput +import groovy.json.JsonSlurper +import groovy.time.TimeCategory +import groovy.time.TimeDuration +import groovy.transform.CompileStatic +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.data.domain.Page +import org.springframework.data.domain.PageRequest +import org.springframework.data.util.Pair +import org.springframework.hateoas.MediaTypes +import org.springframework.security.core.Authentication +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.MvcResult +import org.springframework.web.context.WebApplicationContext + +import java.nio.charset.StandardCharsets + +import static org.junit.jupiter.api.Assertions.assertThrows +import static org.springframework.http.MediaType.APPLICATION_JSON +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post + +@CompileStatic +@SpringBootTest +@ActiveProfiles(["test", "test-transaction"]) +class TransactionTest { + + @Autowired + private TestHelper testHelper + + @Autowired + private ImportHelper importHelper + + @Autowired + private IPetriNetService petriNetService + + @Autowired + private IDataService dataService + + @Autowired + private IWorkflowService workflowService + + @Autowired + private ITaskService taskService + + @Autowired + private TaskRepository taskRepository + + @Autowired + private IElasticPetriNetService elasticPetriNetService + + @Autowired + private IElasticCaseService elasticCaseService + + @Autowired + private IElasticTaskService elasticTaskService + + @Autowired + private SuperCreator superCreator + + @Autowired + private WebApplicationContext wac + + private Process testProcess + private Authentication auth + private MockMvc mvc + private static final String CASE_CREATE_URL = "/api/workflow/case" + private static final String ASSIGN_TASK_URL = "/api/task/assign/" + private static final String SET_GET_DATA_URL_TEMPLATE = "/api/task/%s/data" + private static final String FINISH_TASK_URL = "/api/task/finish/" + + @BeforeEach + void before() throws IOException, MissingPetriNetMetaDataException { + testHelper.truncateDbs() + testProcess = petriNetService.importProcess(new ImportProcessParams( + new FileInputStream("src/test/resources/petriNets/transaction/transaction_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)).getProcess() + TestHelper.login(superCreator.getSuperIdentity()) + } + + @Test + void testBasicTransaction() { + Case useCase = importHelper.createCase("test", testProcess) + useCase = dataService.setData(new SetDataParams(useCase, new DataSet(["testBasicTransaction": new ButtonField(rawValue: 1)] + as Map>), superCreator.getLoggedSuper().activeActorId)).case + + assert findAllByIdentifier("transaction_test").size() == 4 + + assert findCaseByTitle("onButton") + assert findCaseByTitle("onCommit") + assert findCaseByTitle("onAlways") + assert !findCaseByTitle("onRollBack") + + assert countTestCaseTasks() == 4 + + assert useCase.getDataSet().get("text_without_action").getValue().getValue() == "xxx" + assert useCase.getDataSet().get("was_transaction_rolled_back").getValue().getValue() == false + } + + @Test + void testBasicTransactionWithFailure() { + importHelper.createCase("toBeRemoved", testProcess) + Case useCase = createTestCaseAndSetButton("test", "testBasicTransactionWithFailure") + + assert findAllByIdentifier("transaction_test").size() == 4 + + assert !findCaseByTitle("onButton") + assert !findCaseByTitle("onCommit") + assert findCaseByTitle("onAlways") + assert findCaseByTitle("onRollBack") + assert findCaseByTitle("toBeRemoved") + + assert countTestCaseTasks() == 4 + + assert useCase.getDataSet().get("text_without_action").getValue() == null + assert useCase.getDataSet().get("was_transaction_rolled_back").getValue().getValue() == true + } + + @Test + void testFailureInCallBackThrowsError() { + assertThrows(RuntimeException.class, { + createTestCaseAndSetButton("test", "testFailureInCallBackThrowsError") + }) + assert findAllByIdentifier("transaction_test").size() == 1 + assert !findCaseByTitle("onAlways") + + assert countTestCaseTasks() == 1 + } + + @Test + void testTimeout() { + Case useCase = createTestCaseAndSetButton("test", "testTimeout") + + assert findAllByIdentifier("transaction_test").size() == 3 + + assert !findCaseByTitle("onButton") + assert !findCaseByTitle("onCommit") + assert findCaseByTitle("onAlways") + assert findCaseByTitle("onRollBack") + + assert countTestCaseTasks() == 3 + + assert useCase.getDataSet().get("was_transaction_rolled_back").getValue().getValue() == true + } + + @Test + void testElasticIndexingOnTransactionFailure() { + Case useCase = createTestCaseAndSetButton("test", "testElasticIndexingOnTransactionFailure") + + Thread.sleep(2000) // wait for indexation + + assert findAllByIdentifier("transaction_test").size() == 3 + + assert !existPetriNetInElastic("transaction_test_secondary") + assert !existCaseInElastic("toBeRemoved") + assert !existCaseInElastic("toBeRemovedNestedOnFailure") + + assert !existCaseInElastic("onButton") + assert existCaseInElastic("onRollBack") + assert existCaseInElastic("onAlways") + + assert countTestCaseTasksElastic() == 3 + + assert useCase.getDataSet().get("was_transaction_rolled_back").getValue().getValue() == true + } + + @Test + void testElasticIndexingOnTransactionSuccess() { + Case useCase = createTestCaseAndSetButton("test", "testElasticIndexingOnTransactionSuccess") + + Thread.sleep(4000) // wait for indexation + + assert findAllByIdentifier("transaction_test").size() == 5 + + assert existPetriNetInElastic("transaction_test_secondary") + + assert !existCaseInElastic("toBeRemoved") + assert existCaseInElastic("toBeRemovedNestedOnFailure") + assert existCaseInElastic("onButton") + assert existCaseInElastic("onCommit") + assert existCaseInElastic("onAlways") + + assert countTestCaseTasksElastic() == 5 + + assert useCase.getDataSet().get("was_transaction_rolled_back").getValue().getValue() == false + } + + @Test + void testTransactionWriteConflict() { + Case useCase = createTestCaseAndSetButton("test", "testTransactionWriteConflict") + + assert findAllByIdentifier("transaction_test").size() == 5 + + assert findCaseByTitle("onRollBackNested") + assert !findCaseByTitle("onCommitNested") + assert findCaseByTitle("onAlwaysNested") + assert findCaseByTitle("onCommit") + assert findCaseByTitle("onAlways") + + assert countTestCaseTasks() == 5 + + useCase = workflowService.findOne(useCase.stringId) + assert useCase.getDataSet().get("text_without_action").getValue().getValue() == "not nested" + } + + @Test + void testNestedJoinedTransactions() { + Case useCase = createTestCaseAndSetButton("test", "testNestedJoinedTransactions") + + assert findAllByIdentifier("transaction_test").size() == 7 + assert findCaseByTitle("onButton") + assert findCaseByTitle("onCommit") + assert findCaseByTitle("onAlways") + assert findCaseByTitle("onButtonNested") + assert findCaseByTitle("onCommitNested") + assert findCaseByTitle("onAlwaysNested") + assert !findCaseByTitle("onRollBack") + assert !findCaseByTitle("onRollBackNested") + assert useCase.getDataSet().get("was_transaction_rolled_back").getValue().getValue() == false + } + + @Test + void testNestedDifferentTransactions() { + Case useCase = createTestCaseAndSetButton("test", "testNestedDifferentTransactions") + + assert findAllByIdentifier("transaction_test").size() == 7 + assert findCaseByTitle("onButton") + assert findCaseByTitle("onCommit") + assert findCaseByTitle("onAlways") + assert findCaseByTitle("onButtonNested") + assert findCaseByTitle("onCommitNested") + assert findCaseByTitle("onAlwaysNested") + assert !findCaseByTitle("onRollBack") + assert !findCaseByTitle("onRollBackNested") + assert useCase.getDataSet().get("was_transaction_rolled_back").getValue().getValue() == false + } + + @Test + void testNestedJoinedTransactionsWithFailureInParentTransaction() { + Case useCase = createTestCaseAndSetButton("test", "testNestedJoinedTransactionsWithFailureInParentTransaction") + + assert findAllByIdentifier("transaction_test").size() == 4 + assert !findCaseByTitle("onButton") + assert !findCaseByTitle("onCommit") + assert findCaseByTitle("onAlways") + assert !findCaseByTitle("onButtonNested") + assert !findCaseByTitle("onCommitNested") + assert !findCaseByTitle("onAlwaysNested") + assert findCaseByTitle("onRollBack") + assert findCaseByTitle("onRollBackNested") + assert useCase.getDataSet().get("was_transaction_rolled_back").getValue().getValue() == true + } + + @Test + void testNestedJoinedTransactionsWithFailureInNestedTransaction() { + Case useCase = createTestCaseAndSetButton("test", "testNestedJoinedTransactionsWithFailureInNestedTransaction") + + assert findAllByIdentifier("transaction_test").size() == 4 + assert !findCaseByTitle("onButton") + assert !findCaseByTitle("onCommit") + assert findCaseByTitle("onAlways") + assert !findCaseByTitle("onButtonNested") + assert !findCaseByTitle("onCommitNested") + assert !findCaseByTitle("onAlwaysNested") + assert findCaseByTitle("onRollBack") + assert findCaseByTitle("onRollBackNested") + assert useCase.getDataSet().get("was_transaction_rolled_back").getValue().getValue() == true + } + + @Test + void testNestedDifferentTransactionsWithFailureInParentTransaction() { + Case useCase = createTestCaseAndSetButton("test", "testNestedDifferentTransactionsWithFailureInParentTransaction") + + assert findAllByIdentifier("transaction_test").size() == 5 + assert !findCaseByTitle("onButton") + assert !findCaseByTitle("onCommit") + assert findCaseByTitle("onAlways") + assert findCaseByTitle("onButtonNested") + assert findCaseByTitle("onCommitNested") + assert !findCaseByTitle("onAlwaysNested") + assert findCaseByTitle("onRollBack") + assert !findCaseByTitle("onRollBackNested") + assert useCase.getDataSet().get("was_transaction_rolled_back").getValue().getValue() == true // is overridden from false to true + } + + @Test + void testNestedDifferentTransactionsWithFailureInNestedTransaction() { + Case useCase = createTestCaseAndSetButton("test", "testNestedDifferentTransactionsWithFailureInNestedTransaction") + + assert findAllByIdentifier("transaction_test").size() == 6 + assert findCaseByTitle("onButton") + assert findCaseByTitle("onCommit") + assert findCaseByTitle("onAlways") + assert !findCaseByTitle("onButtonNested") + assert !findCaseByTitle("onCommitNested") + assert findCaseByTitle("onAlwaysNested") + assert !findCaseByTitle("onRollBack") + assert findCaseByTitle("onRollBackNested") + assert useCase.getDataSet().get("was_transaction_rolled_back").getValue().getValue() == false // is overridden from true to false + } + + @Test + void testRollBackErrorCurrying() { + Case useCase = createTestCaseAndSetButton("test", "testRollBackErrorCurrying") + + assert findAllByIdentifier("transaction_test").size() == 3 + assert !findCaseByTitle("onButton") + assert !findCaseByTitle("onCommit") + assert findCaseByTitle("onAlways") + assert findCaseByTitle("argument is initialized") + assert useCase.getDataSet().get("was_transaction_rolled_back").getValue().getValue() == true + } + + @Test + @Disabled + void testPerformance() { + beforeMvcTest() + + Process process = petriNetService.importProcess(new ImportProcessParams( + new FileInputStream("src/test/resources/petriNets/mortgage.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)).getProcess() + + int iterations = 500 + long totalCreateCaseDuration = 0 + long totalAssignTaskDuration = 0 + long totalGetDataDuration = 0 + long totalSetDataDuration = 0 + long totalFinishTaskDuration = 0 + (0..iterations).each {idx -> + Pair createCasePair = createCase(process.stringId, "Case" + idx) + totalCreateCaseDuration += createCasePair.first.toMilliseconds() + String taskId = createCasePair.second["tasks"]["t2"]["taskStringId"] + Pair assignTaskPair = assignTask(taskId) + totalAssignTaskDuration += assignTaskPair.first.toMilliseconds() + TimeDuration getDataDuration = getData(taskId) + totalGetDataDuration += getDataDuration.toMilliseconds() + TimeDuration setDataDuration = setData(taskId, "surname", "xxxx") + totalSetDataDuration += setDataDuration.toMilliseconds() + // todo mvc.finishTask requires some additional changed due to problem with user.getLoggedUser() (password is not initialized) + Pair finishTaskPair = finishTask(taskId) + totalFinishTaskDuration += finishTaskPair.first.toMilliseconds() + } + + println("AVG for " + iterations + " iterations createCase is " + totalCreateCaseDuration / iterations + " ms") + println("AVG for " + iterations + " iterations assignTask is " + totalAssignTaskDuration / iterations + " ms") + println("AVG for " + iterations + " iterations getData is " + totalGetDataDuration / iterations + " ms") + println("AVG for " + iterations + " iterations setData is " + totalSetDataDuration / iterations + " ms") + println("AVG for " + iterations + " iterations finishTask is " + totalFinishTaskDuration / iterations + " ms") + } + + private Case createTestCaseAndSetButton(String title, String buttonFieldId) { + Case useCase = importHelper.createCase(title, testProcess) + return dataService.setData(new SetDataParams(useCase, new DataSet([(buttonFieldId): new ButtonField(rawValue: 1)] + as Map>), superCreator.getLoggedSuper().activeActorId)).getCase() + } + + private Case findCaseByTitle(String title) { + Page caseAsPage = workflowService.search(QCase.case$.title.eq(title), PageRequest.of(0, 1)) + if (caseAsPage.totalElements > 0) { + return caseAsPage.first() + } else { + return null + } + } + + private long countTestCaseTasks() { + return taskRepository.count(QTask.task.processId.eq(testProcess.getStringId()) & QTask.task.transitionId.eq("t1")); + } + + private List findAllByIdentifier(String identifier) { + Page caseAsPage = workflowService.search(QCase.case$.processIdentifier.eq(identifier), PageRequest.of(0, Integer.MAX_VALUE)) + if (caseAsPage.totalElements > 0) { + return caseAsPage.getContent() + } else { + return List.of() + } + } + + private boolean existPetriNetInElastic(String identifier) { + return elasticPetriNetService.findAllByIdentifier(identifier).size() >= 1 + } + + private boolean existCaseInElastic(String title) { + return elasticCaseService.count( + List.of(CaseSearchRequest.builder().query("title:" + title).build()), + superCreator.getLoggedSuper().activeActorId, + Locale.getDefault(), + false + ) >= 1 + } + + private long countTestCaseTasksElastic() { + return elasticTaskService.count( + List.of(new ElasticTaskSearchRequest(Map.of("query", (Object) ("processId:" + testProcess.getStringId() + " AND transitionId:t1")))), + superCreator.getLoggedSuper().activeActorId, + Locale.getDefault(), + false + ) + } + + private void beforeMvcTest() { + TestHelper.login(superCreator.getSuperIdentity()) + } + + private Pair createCase(String petriNetStringId, String caseTitle) { + String content = JsonOutput.toJson([ + title: caseTitle, + netId: petriNetStringId, + color: "color" + ]) + Date startTime = new Date() + MvcResult result = mvc.perform(post(CASE_CREATE_URL) + .accept(MediaTypes.HAL_JSON_VALUE) + .content(content) + .contentType(APPLICATION_JSON) + .with(authentication(auth))) + .andReturn() + Date endTime = new Date() + return Pair.of(TimeCategory.minus( endTime, startTime ), ((CreateCaseEventOutcome)((EventOutcomeWithMessage) parseResult(result)).outcome).case) + } + + private Pair assignTask(String taskId) { + Date startTime = new Date() + MvcResult result = mvc.perform(get(ASSIGN_TASK_URL+taskId) + .accept(MediaTypes.HAL_JSON_VALUE) + .contentType(APPLICATION_JSON) + .with(authentication(auth))) + .andReturn() + Date endTime = new Date() + return Pair.of(TimeCategory.minus( endTime, startTime ), ((AssignTaskEventOutcome)((EventOutcomeWithMessage) parseResult(result)).outcome).task) + } + + private Pair finishTask(String taskId) { + Date startTime = new Date() + MvcResult result = mvc.perform(get(FINISH_TASK_URL+taskId) + .accept(MediaTypes.HAL_JSON_VALUE) + .contentType(APPLICATION_JSON) + .with(authentication(auth))) + .andReturn() + Date endTime = new Date() + return Pair.of(TimeCategory.minus( endTime, startTime ), ((FinishTaskEventOutcome)((EventOutcomeWithMessage) parseResult(result)).outcome).task) + } + + private TimeDuration getData(String taskId) { + Date startTime = new Date() + mvc.perform(get(String.format(SET_GET_DATA_URL_TEMPLATE, taskId)) + .contentType(APPLICATION_JSON) + .with(authentication(auth))) + Date endTime = new Date() + return TimeCategory.minus( endTime, startTime ) + } + + private TimeDuration setData(String taskId, String fieldId, String newValue) { + Field surnameField = new TextField() + surnameField.setRawValue(newValue) + + def body = [(taskId): new DataSet([(fieldId): (Field) surnameField])] + + String content = JsonOutput.toJson(new TaskDataSets(body)) + + Date startTime = new Date() + mvc.perform(post(String.format(SET_GET_DATA_URL_TEMPLATE, taskId)) + .content(content) + .contentType(APPLICATION_JSON) + .with(authentication(auth))) + Date endTime = new Date() + return TimeCategory.minus( endTime, startTime ) + } + + @SuppressWarnings("GrMethodMayBeStatic") + private def parseResult(MvcResult result) { + return (new JsonSlurper()).parseText(result.response.getContentAsString(StandardCharsets.UTF_8)) + } + +} diff --git a/src/test/groovy/com/netgrif/application/engine/validation/BooleanFieldValidationTest.groovy b/src/test/groovy/com/netgrif/application/engine/validation/BooleanFieldValidationTest.groovy index c6d8dc4bbda..366c983387c 100644 --- a/src/test/groovy/com/netgrif/application/engine/validation/BooleanFieldValidationTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/validation/BooleanFieldValidationTest.groovy @@ -1,31 +1,29 @@ package com.netgrif.application.engine.validation import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.petrinet.domain.I18nString import com.netgrif.application.engine.petrinet.domain.dataset.BooleanField -import com.netgrif.application.engine.validation.domain.ValidationDataInput -import com.netgrif.application.engine.validation.models.BooleanFieldValidation -import org.junit.jupiter.api.Assertions +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ValidationDelegate import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest -import org.springframework.context.i18n.LocaleContextHolder import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension -import java.util.stream.Collectors @SpringBootTest @ActiveProfiles(["test"]) @ExtendWith(SpringExtension.class) class BooleanFieldValidationTest { - public static final String ErrorMessage = "Invalid Field value" @Autowired private TestHelper testHelper + private static ValidationDelegate getValidationDelegate() { + return new ValidationDelegate() + } + @BeforeEach void setup() { testHelper.truncateDbs() @@ -33,54 +31,32 @@ class BooleanFieldValidationTest { @Test void requiredTrue() { - BooleanFieldValidation booleanFieldValidation = new BooleanFieldValidation() - BooleanField dataField = new BooleanField(rawValue: true) - I18nString validMessage = new I18nString(ErrorMessage) - List rules = [] - ValidationDataInput input = new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" "))) + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new BooleanField(rawValue: true) - booleanFieldValidation.requiredtrue(input) + assert delegate.requiredTrue() } - @Test - void notempty() { - BooleanFieldValidation booleanFieldValidation = new BooleanFieldValidation() - BooleanField dataField = new BooleanField(rawValue: true) - I18nString validMessage = new I18nString(ErrorMessage) - List rules = [] - ValidationDataInput input = new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" "))) + void requiredTrue_fail() { + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new BooleanField(rawValue: false) - booleanFieldValidation.notempty(input) + assert !delegate.requiredTrue() } - @Test - void notempty_Exception() { - BooleanFieldValidation booleanFieldValidation = new BooleanFieldValidation() - BooleanField dataField = new BooleanField() - dataField.value = null - I18nString validMessage = new I18nString(ErrorMessage) - List rules = [] - ValidationDataInput input = new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" "))) + void notempty() { + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new BooleanField(rawValue: true) - IllegalArgumentException thrown = Assertions.assertThrows(IllegalArgumentException.class, () -> { - booleanFieldValidation.notempty(input) - }) - Assertions.assertEquals(ErrorMessage, thrown.getMessage()); + assert delegate.isNotEmpty() } @Test - void notempty_Exception2() { - BooleanFieldValidation booleanFieldValidation = new BooleanFieldValidation() - BooleanField dataField = new BooleanField() - dataField.value = null - I18nString validMessage = new I18nString(ErrorMessage) - List rules = [] - ValidationDataInput input = new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" "))) + void notempty_fail() { + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new BooleanField(rawValue: null) - IllegalArgumentException thrown = Assertions.assertThrows(IllegalArgumentException.class, () -> { - booleanFieldValidation.notempty(input) - }) - Assertions.assertEquals(ErrorMessage, thrown.getMessage()); + assert !delegate.isNotEmpty() } } diff --git a/src/test/groovy/com/netgrif/application/engine/validation/NumberFieldValidationTest.groovy b/src/test/groovy/com/netgrif/application/engine/validation/NumberFieldValidationTest.groovy index a4aa85ed99e..0a6f62a0a13 100644 --- a/src/test/groovy/com/netgrif/application/engine/validation/NumberFieldValidationTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/validation/NumberFieldValidationTest.groovy @@ -1,100 +1,138 @@ package com.netgrif.application.engine.validation import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.petrinet.domain.I18nString import com.netgrif.application.engine.petrinet.domain.dataset.NumberField -import com.netgrif.application.engine.validation.domain.ValidationDataInput -import com.netgrif.application.engine.validation.models.NumberFieldValidation +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ValidationDelegate import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest -import org.springframework.context.i18n.LocaleContextHolder import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension -import java.util.stream.Collectors +import static org.junit.jupiter.api.Assertions.assertThrows @SpringBootTest @ActiveProfiles(["test"]) @ExtendWith(SpringExtension.class) class NumberFieldValidationTest { + private static final INF = 'inf' @Autowired private TestHelper testHelper + private static ValidationDelegate getValidationDelegate() { + return new ValidationDelegate() + } + @BeforeEach void setup() { testHelper.truncateDbs() } - @Test void odd() { - NumberFieldValidation numberFieldValidation = new NumberFieldValidation() - NumberField dataField = new NumberField(rawValue: 5) - I18nString validMessage = new I18nString("Invalid Field value") - List rules = [] - ValidationDataInput input = new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" "))) + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new NumberField(rawValue: 5) - numberFieldValidation.odd(input) + assert delegate.odd() } + @Test + void odd_fail() { + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new NumberField(rawValue: 4) + + assert !delegate.odd() + } @Test void even() { - NumberFieldValidation numberFieldValidation = new NumberFieldValidation() - NumberField dataField = new NumberField(rawValue: 4) - I18nString validMessage = new I18nString("Invalid Field value") - List rules = [] - ValidationDataInput input = new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" "))) + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new NumberField(rawValue: 4) + + assert delegate.even() + } - numberFieldValidation.even(input) + @Test + void even_fail() { + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new NumberField(rawValue: 5) + + assert !delegate.even() } @Test void positive() { - NumberFieldValidation numberFieldValidation = new NumberFieldValidation() - NumberField dataField = new NumberField(rawValue: 4) - I18nString validMessage = new I18nString("Invalid Field value") - List rules = [] - ValidationDataInput input = new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" "))) + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new NumberField(rawValue: 4) + + assert delegate.positive() + } - numberFieldValidation.positive(input) + @Test + void positive_fail() { + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new NumberField(rawValue: -4) + + assert !delegate.positive() } @Test - void positivenegative() { - NumberFieldValidation numberFieldValidation = new NumberFieldValidation() - NumberField dataField = new NumberField(rawValue: -4) - I18nString validMessage = new I18nString("Invalid Field value") - List rules = [] - ValidationDataInput input = new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" "))) - - numberFieldValidation.negative(input) + void negative() { + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new NumberField(rawValue: -4) + + assert delegate.negative() + } + + @Test + void negative_fail() { + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new NumberField(rawValue: 4) + + assert !delegate.negative() } @Test void decimal() { - NumberFieldValidation numberFieldValidation = new NumberFieldValidation() - NumberField dataField = new NumberField(rawValue: 4) - I18nString validMessage = new I18nString("Invalid Field value") - List rules = [] - ValidationDataInput input = new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" "))) + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new NumberField(rawValue: 4) + + assert delegate.decimal() + } + + @Test + void decimal_fail() { + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new NumberField(rawValue: 4.1) - numberFieldValidation.decimal(input) + assert !delegate.decimal() } @Test void inrange() { - NumberFieldValidation numberFieldValidation = new NumberFieldValidation() - NumberField dataField = new NumberField(rawValue: 7) - I18nString validMessage = new I18nString("Invalid Field value") - List rules = ["5,10"] - ValidationDataInput input = new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" "))) + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new NumberField(rawValue: 7) + + assert delegate.inrange(5, 10) + + assert delegate.inrange(INF, 10) + + assert delegate.inrange(5, INF) + + assert delegate.inrange(INF, INF) + + assert delegate.inrange("5", "10") + } + + @Test + void inrange_fail() { + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new NumberField(rawValue: 7) - numberFieldValidation.inrange(input) + assertThrows(NumberFormatException.class, { !delegate.inrange('totok', INF) }) } } diff --git a/src/test/groovy/com/netgrif/application/engine/validation/TextFieldValidationTest.groovy b/src/test/groovy/com/netgrif/application/engine/validation/TextFieldValidationTest.groovy index e806d4b9a96..6ff621caa0a 100644 --- a/src/test/groovy/com/netgrif/application/engine/validation/TextFieldValidationTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/validation/TextFieldValidationTest.groovy @@ -1,61 +1,58 @@ package com.netgrif.application.engine.validation import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.petrinet.domain.I18nString import com.netgrif.application.engine.petrinet.domain.dataset.TextField -import com.netgrif.application.engine.validation.domain.ValidationDataInput -import com.netgrif.application.engine.validation.models.TextFieldValidation -import org.junit.jupiter.api.Assertions +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ValidationDelegate + +//import com.netgrif.application.engine.validation.domain.ValidationDataInput +//import com.netgrif.application.engine.validation.models.TextFieldValidation + import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest -import org.springframework.context.i18n.LocaleContextHolder import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension -import java.util.stream.Collectors - @SpringBootTest @ActiveProfiles(["test"]) @ExtendWith(SpringExtension.class) class TextFieldValidationTest { - public static final String ErrorMessage = "Invalid Field value" @Autowired private TestHelper testHelper + private static ValidationDelegate getValidationDelegate() { + return new ValidationDelegate() + } + @BeforeEach void setup() { testHelper.truncateDbs() } @Test - void minlength_Exception() { - TextFieldValidation textFieldValidation = new TextFieldValidation() - TextField dataField = new TextField(rawValue: 'totok') - I18nString validMessage = new I18nString(ErrorMessage) - List rules = ["minlength","6"] - ValidationDataInput input = new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" "))) - - IllegalArgumentException thrown = Assertions.assertThrows(IllegalArgumentException.class, () -> { - textFieldValidation.minlength(input) - }) - Assertions.assertEquals(ErrorMessage, thrown.getMessage()); + void minlength() { + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new TextField(rawValue: 'totok') + + assert !delegate.minlength(6) + + assert delegate.minlength(5) + + assert delegate.minlength(4) } @Test - void maxlength_Exception() { - TextFieldValidation textFieldValidation = new TextFieldValidation() - TextField dataField = new TextField(rawValue: 'totok') - I18nString validMessage = new I18nString(ErrorMessage) - List rules = ["maxlength","4"] - ValidationDataInput input = new ValidationDataInput(dataField, validMessage, LocaleContextHolder.getLocale(), rules.stream().skip(1).collect(Collectors.joining(" "))) - - IllegalArgumentException thrown = Assertions.assertThrows(IllegalArgumentException.class, () -> { - textFieldValidation.maxlength(input) - }) - Assertions.assertEquals(ErrorMessage, thrown.getMessage()); + void maxlength() { + ValidationDelegate delegate = getValidationDelegate() + delegate.field = new TextField(rawValue: 'totok') + + assert !delegate.maxlength(4) + + assert delegate.maxlength(5) + + assert delegate.maxlength(6) } } diff --git a/src/test/groovy/com/netgrif/application/engine/validation/ValidationTest.groovy b/src/test/groovy/com/netgrif/application/engine/validation/ValidationTest.groovy index 4e640f09792..f28738aa0a9 100644 --- a/src/test/groovy/com/netgrif/application/engine/validation/ValidationTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/validation/ValidationTest.groovy @@ -1,91 +1,70 @@ package com.netgrif.application.engine.validation +import com.netgrif.application.engine.EngineTest import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.dataset.BooleanField import com.netgrif.application.engine.petrinet.domain.dataset.DateField import com.netgrif.application.engine.petrinet.domain.dataset.NumberField import com.netgrif.application.engine.petrinet.domain.dataset.TextField -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.Task -import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import com.netgrif.application.engine.workflow.web.responsebodies.DataSet -import org.junit.Ignore import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension import java.time.LocalDate -import java.time.format.DateTimeFormatter @SpringBootTest @ActiveProfiles(["test"]) @ExtendWith(SpringExtension.class) -class ValidationTest { +class ValidationTest extends EngineTest { - @Autowired - private ImportHelper importHelper - - @Autowired - private CaseRepository caseRepository - - @Autowired - private TestHelper testHelper - - @Autowired - private IPetriNetService petriNetService - - @Autowired - private SuperCreator superCreator - - @BeforeEach - void setup() { - testHelper.truncateDbs() - } - - private PetriNet importTextNet() { - PetriNet testNet = importHelper.createNet("validation/valid_text.xml", VersionType.MAJOR).get() + private Process importTextNet() { + Process testNet = importHelper.createNet("validation/valid_text.xml", VersionType.MAJOR).get() assert testNet != null return testNet } - private PetriNet importRegexNet() { - PetriNet testNet = importHelper.createNet("validation/valid_regex.xml", VersionType.MAJOR).get() + private Process importRegexNet() { + Process testNet = importHelper.createNet("validation/valid_regex.xml", VersionType.MAJOR).get() assert testNet != null return testNet } - private PetriNet importBooleanNet() { - PetriNet testNet = importHelper.createNet("validation/valid_boolean.xml", VersionType.MAJOR).get() + private Process importBooleanNet() { + Process testNet = importHelper.createNet("validation/valid_boolean.xml", VersionType.MAJOR).get() assert testNet != null return testNet } - private PetriNet importDateNet() { - PetriNet testNet = importHelper.createNet("validation/valid_date.xml", VersionType.MAJOR).get() + private Process importDateNet() { + Process testNet = importHelper.createNet("validation/valid_date.xml", VersionType.MAJOR).get() assert testNet != null return testNet } - private PetriNet importNumberNet() { - PetriNet testNet = importHelper.createNet("validation/valid_number.xml", VersionType.MAJOR).get() + private Process importNumberNet() { + Process testNet = importHelper.createNet("validation/valid_number.xml", VersionType.MAJOR).get() assert testNet != null return testNet } + @BeforeEach + void before() { + TestHelper.login(superCreator.superIdentity) + } + // TEXT FIELD @Test void textValid_email() { - PetriNet testNet = importTextNet() + Process testNet = importTextNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -97,7 +76,7 @@ class ValidationTest { @Test void textValid_email2() { - PetriNet testNet = importTextNet() + Process testNet = importTextNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -109,7 +88,7 @@ class ValidationTest { @Test void textValid_email3() { - PetriNet testNet = importTextNet() + Process testNet = importTextNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -121,7 +100,7 @@ class ValidationTest { @Test void textValid_email_Exception() { - PetriNet testNet = importTextNet() + Process testNet = importTextNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -136,7 +115,7 @@ class ValidationTest { @Test void textValid_email_Exception2() { - PetriNet testNet = importTextNet() + Process testNet = importTextNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -152,7 +131,7 @@ class ValidationTest { @Test void textValid_telnumber() { - PetriNet testNet = importTextNet() + Process testNet = importTextNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -164,7 +143,7 @@ class ValidationTest { @Test void textValid_telnumber2() { - PetriNet testNet = importTextNet() + Process testNet = importTextNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -176,7 +155,7 @@ class ValidationTest { @Test void textValid_telnumber3() { - PetriNet testNet = importTextNet() + Process testNet = importTextNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -188,7 +167,7 @@ class ValidationTest { @Test void textValid_telnumber4() { - PetriNet testNet = importTextNet() + Process testNet = importTextNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -200,7 +179,7 @@ class ValidationTest { @Test void textValid_telnumber_Exception() { - PetriNet testNet = importTextNet() + Process testNet = importTextNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -216,7 +195,7 @@ class ValidationTest { @Test void regexValid_regex01() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -228,7 +207,7 @@ class ValidationTest { @Test void regexValid_regex02() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -240,7 +219,7 @@ class ValidationTest { @Test void regexValid_regex03() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -252,7 +231,7 @@ class ValidationTest { @Test void regexValid_regex04() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -264,7 +243,7 @@ class ValidationTest { @Test void regexValid_regex05() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -276,7 +255,7 @@ class ValidationTest { @Test void regexValid_regex05_2() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -288,7 +267,7 @@ class ValidationTest { @Test void regexValid_regex06() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -300,7 +279,7 @@ class ValidationTest { @Test void regexValid_regex06_2() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -312,7 +291,7 @@ class ValidationTest { @Test void regexValid_regex06_3() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -324,7 +303,7 @@ class ValidationTest { @Test void regexValid_regex01_Exception() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -340,7 +319,7 @@ class ValidationTest { @Test void regexValid_regex01_Exception2() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -356,7 +335,7 @@ class ValidationTest { @Test void regexValid_regex01_Exception3() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -372,7 +351,7 @@ class ValidationTest { @Test void regexValid_regex02_Exception() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -388,7 +367,7 @@ class ValidationTest { @Test void regexValid_regex02_Exception2() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -404,7 +383,7 @@ class ValidationTest { @Test void regexValid_regex02_Exception3() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -420,7 +399,7 @@ class ValidationTest { @Test void regexValid_regex03_Exception() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -436,7 +415,7 @@ class ValidationTest { @Test void regexValid_regex03_Exception2() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -452,7 +431,7 @@ class ValidationTest { @Test void regexValid_regex03_Exception3() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -468,7 +447,7 @@ class ValidationTest { @Test void regexValid_regex04_Exception() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -484,7 +463,7 @@ class ValidationTest { @Test void regexValid_regex05_Exception() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -500,7 +479,7 @@ class ValidationTest { @Test void regexValid_regex06_Exception() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -516,7 +495,7 @@ class ValidationTest { @Test void regexValid_regex06_Exception2() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -532,7 +511,7 @@ class ValidationTest { @Test void regexValid_regex06_Exception3() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -548,7 +527,7 @@ class ValidationTest { @Test void regexValid_regex06_Exception4() { - PetriNet testNet = importRegexNet() + Process testNet = importRegexNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -565,26 +544,26 @@ class ValidationTest { // BOOLEAN FIELD @Test void booleanValid_requiredTrue() { - PetriNet testNet = importBooleanNet() + Process testNet = importBooleanNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() assert task != null - importHelper.setTaskData(task.getStringId(), new DataSet(["boolean_0": new BooleanField(rawValue:true)])) + importHelper.setTaskData(task.getStringId(), new DataSet(["boolean_0": new BooleanField(rawValue: true)])) Task taskFinish = importHelper.finishTaskAsSuper("Test", aCase.stringId).getTask() assert taskFinish != null } @Test void booleanValid_requiredTrue_Exception() { - PetriNet testNet = importBooleanNet() + Process testNet = importBooleanNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() assert task != null IllegalArgumentException thrown = Assertions.assertThrows(IllegalArgumentException.class, () -> { - importHelper.setTaskData(task.getStringId(), new DataSet(["boolean_0": new BooleanField(rawValue:false)])) + importHelper.setTaskData(task.getStringId(), new DataSet(["boolean_0": new BooleanField(rawValue: false)])) Task taskFinish = importHelper.finishTaskAsSuper("Test", aCase.stringId).getTask() assert taskFinish != null }) @@ -593,7 +572,7 @@ class ValidationTest { @Test void booleanValid_requiredTrue_Exception2() { - PetriNet testNet = importBooleanNet() + Process testNet = importBooleanNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -610,7 +589,7 @@ class ValidationTest { // DATE FIELD @Test void dateValid_between_today() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -622,7 +601,7 @@ class ValidationTest { @Test void dateValid_between_today_plusDay() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -634,7 +613,7 @@ class ValidationTest { @Test void dateValid_between_today_Exception() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -649,7 +628,7 @@ class ValidationTest { @Test void dateValid_between_past() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -661,7 +640,7 @@ class ValidationTest { @Test void dateValid_between_past_minusDay() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -673,7 +652,7 @@ class ValidationTest { @Test void dateValid_between_past_Exception() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -688,7 +667,7 @@ class ValidationTest { @Test void dateValid_between_fromDate() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -700,7 +679,7 @@ class ValidationTest { @Test void dateValid_between_fromDate_today() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -712,7 +691,7 @@ class ValidationTest { @Test void dateValid_between_fromDate_Exception() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -727,7 +706,7 @@ class ValidationTest { @Test void dateValid_between_fromDate_past() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -739,7 +718,7 @@ class ValidationTest { @Test void dateValid_between_fromDate_past_minusDay() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -751,7 +730,7 @@ class ValidationTest { @Test void dateValid_between_fromDate_past_Exception() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -767,7 +746,7 @@ class ValidationTest { @Test void dateValid_between_fromDate_toDate() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -779,37 +758,37 @@ class ValidationTest { @Test void dateValid_between_fromDate_toDate2() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() assert task != null - importHelper.setTaskData(task.getStringId(), new DataSet(["date05": new DateField(rawValue: LocalDate.of(2022,3,3))])) + importHelper.setTaskData(task.getStringId(), new DataSet(["date05": new DateField(rawValue: LocalDate.of(2022, 3, 3))])) Task taskFinish = importHelper.finishTaskAsSuper("Test", aCase.stringId).getTask() assert taskFinish != null } @Test void dateValid_workday() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() assert task != null - importHelper.setTaskData(task.getStringId(), new DataSet(["date06": new DateField(rawValue: LocalDate.of(1994,7,4))])) + importHelper.setTaskData(task.getStringId(), new DataSet(["date06": new DateField(rawValue: LocalDate.of(1994, 7, 4))])) Task taskFinish = importHelper.finishTaskAsSuper("Test", aCase.stringId).getTask() assert taskFinish != null } @Test void dateValid_workday_Exception() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() assert task != null IllegalArgumentException thrown = Assertions.assertThrows(IllegalArgumentException.class, () -> { - importHelper.setTaskData(task.getStringId(), new DataSet(["date06": new DateField(rawValue: LocalDate.of(1994,7,3))])) + importHelper.setTaskData(task.getStringId(), new DataSet(["date06": new DateField(rawValue: LocalDate.of(1994, 7, 3))])) Task taskFinish = importHelper.finishTaskAsSuper("Test", aCase.stringId).getTask() assert taskFinish != null }) @@ -818,25 +797,25 @@ class ValidationTest { @Test void dateValid_weekend() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() assert task != null - importHelper.setTaskData(task.getStringId(), new DataSet(["date07": new DateField(rawValue: LocalDate.of(1994,7,3))])) + importHelper.setTaskData(task.getStringId(), new DataSet(["date07": new DateField(rawValue: LocalDate.of(1994, 7, 3))])) Task taskFinish = importHelper.finishTaskAsSuper("Test", aCase.stringId).getTask() assert taskFinish != null } @Test void dateValid_weekend_Exception() { - PetriNet testNet = importDateNet() + Process testNet = importDateNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() assert task != null IllegalArgumentException thrown = Assertions.assertThrows(IllegalArgumentException.class, () -> { - importHelper.setTaskData(task.getStringId(), new DataSet(["date07": new DateField(rawValue: LocalDate.of(1994,7,4))])) + importHelper.setTaskData(task.getStringId(), new DataSet(["date07": new DateField(rawValue: LocalDate.of(1994, 7, 4))])) Task taskFinish = importHelper.finishTaskAsSuper("Test", aCase.stringId).getTask() assert taskFinish != null }) @@ -846,7 +825,7 @@ class ValidationTest { // Number Field @Test void numberValid_odd() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -858,7 +837,7 @@ class ValidationTest { @Test void numberValid_odd_Exception() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -874,7 +853,7 @@ class ValidationTest { @Test void numberValid_even() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -886,7 +865,7 @@ class ValidationTest { @Test void numberValid_even_Exception() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -902,7 +881,7 @@ class ValidationTest { @Test void numberValid_positive() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -914,7 +893,7 @@ class ValidationTest { @Test void numberValid_positive_Exception() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -930,7 +909,7 @@ class ValidationTest { @Test void numberValid_negative() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -942,7 +921,7 @@ class ValidationTest { @Test void numberValid_negative_Exception() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -958,7 +937,7 @@ class ValidationTest { @Test void numberValid_decimal() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -970,7 +949,7 @@ class ValidationTest { @Test void numberValid_decimal_Exception() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -986,7 +965,7 @@ class ValidationTest { @Test void numberValid_inRange() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -998,7 +977,7 @@ class ValidationTest { @Test void numberValid_inRange_Exception() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -1015,7 +994,7 @@ class ValidationTest { @Test void numberValid_inRange_odd() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -1027,7 +1006,7 @@ class ValidationTest { @Test void numberValid_inRange_odd_Exception() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() @@ -1043,7 +1022,7 @@ class ValidationTest { @Test void numberValid_inRange_odd_Exception2() { - PetriNet testNet = importNumberNet() + Process testNet = importNumberNet() Case aCase = importHelper.createCase("TestCase", testNet) assert aCase != null Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() diff --git a/src/test/groovy/com/netgrif/application/engine/validation/ValidationTestDynamic.groovy b/src/test/groovy/com/netgrif/application/engine/validation/ValidationTestDynamic.groovy new file mode 100644 index 00000000000..4b08b5b9838 --- /dev/null +++ b/src/test/groovy/com/netgrif/application/engine/validation/ValidationTestDynamic.groovy @@ -0,0 +1,310 @@ +package com.netgrif.application.engine.validation + +import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.petrinet.domain.Process +import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.dataset.Field +import com.netgrif.application.engine.petrinet.domain.dataset.MultichoiceMapField +import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService +import com.netgrif.application.engine.startup.ImportHelper +import com.netgrif.application.engine.startup.ValidationRunner +import com.netgrif.application.engine.validations.interfaces.IValidationService +import com.netgrif.application.engine.workflow.domain.Case +import com.netgrif.application.engine.workflow.domain.Task +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.dataoutcomes.SetDataEventOutcome +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService +import com.netgrif.application.engine.workflow.web.responsebodies.DataSet +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.context.junit.jupiter.SpringExtension + +@SpringBootTest +@ActiveProfiles(["test"]) +@ExtendWith(SpringExtension.class) +class ValidationTestDynamic { + + public static final String VALIDATION_PETRI_NET_IDENTIFIER = "validation" + public static final String VALIDATION_NAME_FIELD_ID = "name" + public static final String VALIDATION_VALIDATION_TYPE_FIELD_ID = "validation_type" + public static final String VALIDATION_DEFINITION_GROOVY_FIELD_ID = "validation_definition_groovy" + public static final String VALIDATION_NUM_ARGUMENTS_GROOVY_FIELD_ID = "num_arguments_groovy" + public static final String VALIDATION_DEFINITION_JAVASCRIPT_FIELD_ID = "validation_definition_javascript" + public static final String VALIDATION_NUM_ARGUMENTS_JAVASCRIPT_FIELD_ID = "num_arguments_javascript" + public static final String VALIDATION_INIT_TRANS_ID = "init" + public static final String VALIDATION_DETAIL_TRANS_ID = "detail" + + @Autowired + private ImportHelper importHelper + + @Autowired + private TestHelper testHelper + + @Autowired + private IPetriNetService petriNetService + + @Autowired + private IWorkflowService workflowService + + @Autowired + private IValidationService validationService + + @Autowired + protected ValidationRunner validationRunner + + @BeforeEach + void setup() { + testHelper.truncateDbs() + validationService.clearValidations() + } + + private Process importTextNet() { + Process testNet = importHelper.createNet("validation/valid_text.xml", VersionType.MAJOR).get() + assert testNet != null + return testNet + } + + private Case createValidation(String name, String validationDefinitionGroovy, Boolean active = true) { + Process net = petriNetService.getNewestVersionByIdentifier(VALIDATION_PETRI_NET_IDENTIFIER) + + Case validationCase = importHelper.createCase("Validation ${name}", net) + assert validationCase != null + + Task validationTask = importHelper.assignTaskToSuper("Init", validationCase.stringId).getTask() + assert validationTask != null + + SetDataEventOutcome outcome = importHelper.setTaskData("Init", validationCase.stringId, new DataSet([ + (VALIDATION_NAME_FIELD_ID): new TextField(rawValue: name), + (VALIDATION_VALIDATION_TYPE_FIELD_ID): new MultichoiceMapField(rawValue: ["server"]), + (VALIDATION_DEFINITION_GROOVY_FIELD_ID): new TextField(rawValue: validationDefinitionGroovy) + ] as Map>)) + assert outcome != null + + validationTask = importHelper.finishTaskAsSuper("Init", validationCase.stringId).getTask() + assert validationTask != null + + if (active) { + validationTask = importHelper.assignTaskToSuper("Activate", validationCase.stringId).getTask() + assert validationTask != null + + validationTask = importHelper.finishTaskAsSuper("Activate", validationCase.stringId).getTask() + assert validationTask != null + } + + validationCase = workflowService.findOne(validationCase.stringId) + assert validationCase.tasks.get("deactivate") != null + + return validationCase + } + + @Test + void textDynamic_validation() { + createValidation("aaaa", "a -> field.rawValue.size() == a as Integer", true) + + Process testNet = importTextNet() + Case aCase = importHelper.createCase("TestCase", testNet) + assert aCase != null + Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() + assert task != null + importHelper.setTaskData(task.getStringId(), new DataSet(["text06": new TextField(rawValue: "12345")])) + Task taskFinish = importHelper.finishTaskAsSuper("Test", aCase.stringId).getTask() + assert taskFinish != null + } + + @Test + void textDynamic_validation_fail() { + createValidation("aaaa", "a -> field.rawValue.size() == a as Integer", true) + + Process testNet = importTextNet() + Case aCase = importHelper.createCase("TestCase", testNet) + assert aCase != null + Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() + assert task != null + + IllegalArgumentException thrown = Assertions.assertThrows(IllegalArgumentException.class, () -> { + importHelper.setTaskData(task.getStringId(), new DataSet(["text06": new TextField(rawValue: "1234567")])) + Task taskFinish = importHelper.finishTaskAsSuper("Test", aCase.stringId).getTask() + assert taskFinish != null + }) + + assert "error-text06" == thrown.getMessage() + } + + @Test + void textDynamic_validation_conflictWithFieldName() { + createValidation("number01", "a -> field.rawValue.size() == a as Integer", true) + + Process testNet = importTextNet() + Case aCase = importHelper.createCase("TestCase", testNet) + assert aCase != null + Task task = importHelper.assignTaskToSuper("Test", aCase.stringId).getTask() + assert task != null + + Assertions.assertThrows(MissingMethodException.class, () -> { + importHelper.setTaskData(task.getStringId(), new DataSet(["text07": new TextField(rawValue: "1234567")])) + Task taskFinish = importHelper.finishTaskAsSuper("Test", aCase.stringId).getTask() + assert taskFinish != null + }) + } + + @Test + void dynamicValidation_process_importActive() { + createValidation("test1", "-> field.rawValue = 1", true) + createValidation("test2", "-> field.rawValue = 2", true) + createValidation("test3", "-> field.rawValue = 3", false) + + assert validationService.getValidation("test1") instanceof Closure && validationService.getValidation("test1") != null + assert validationService.getValidation("test2") instanceof Closure && validationService.getValidation("test2") != null + assert validationService.getValidation("test3") == null + + validationService.clearValidations() + + assert validationService.getValidation("test1") == null + assert validationService.getValidation("test2") == null + assert validationService.getValidation("test3") == null + + validationRunner.run() + + assert validationService.getValidation("test1") instanceof Closure && validationService.getValidation("test1") != null + assert validationService.getValidation("test2") instanceof Closure && validationService.getValidation("test2") != null + assert validationService.getValidation("test3") == null + } + + @Test + void dynamicValidation_process_behaviors() { + Process net = petriNetService.getNewestVersionByIdentifier(VALIDATION_PETRI_NET_IDENTIFIER) + + Case validationCase = importHelper.createCase("Validation test", net) + assert validationCase != null + + Task validationTask = importHelper.assignTaskToSuper("Init", validationCase.stringId).getTask() + assert validationTask != null + + // TODO: release/8.0.0 +// assert validationCase.dataSet.get(VALIDATION_DEFINITION_GROOVY_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).hidden +// assert validationCase.dataSet.get(VALIDATION_NUM_ARGUMENTS_GROOVY_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).hidden +// assert validationCase.dataSet.get(VALIDATION_DEFINITION_GROOVY_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).hidden +// assert validationCase.dataSet.get(VALIDATION_NUM_ARGUMENTS_GROOVY_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).hidden +// assert validationCase.dataSet.get(VALIDATION_DEFINITION_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).hidden +// assert validationCase.dataSet.get(VALIDATION_NUM_ARGUMENTS_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).hidden +// assert validationCase.dataSet.get(VALIDATION_DEFINITION_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).hidden +// assert validationCase.dataSet.get(VALIDATION_NUM_ARGUMENTS_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).hidden + + SetDataEventOutcome outcome = importHelper.setTaskData("Init", validationCase.stringId, new DataSet([ + (VALIDATION_VALIDATION_TYPE_FIELD_ID): new MultichoiceMapField(rawValue: ["client"]), + ] as Map>)) + assert outcome != null + assert outcome.case.dataSet.get(VALIDATION_DEFINITION_GROOVY_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).hidden + assert outcome.case.dataSet.get(VALIDATION_NUM_ARGUMENTS_GROOVY_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).hidden + assert outcome.case.dataSet.get(VALIDATION_DEFINITION_GROOVY_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).hidden + assert outcome.case.dataSet.get(VALIDATION_NUM_ARGUMENTS_GROOVY_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).hidden + assert outcome.case.dataSet.get(VALIDATION_DEFINITION_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_NUM_ARGUMENTS_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_DEFINITION_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_NUM_ARGUMENTS_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).editable + + outcome = importHelper.setTaskData("Init", validationCase.stringId, new DataSet([ + (VALIDATION_VALIDATION_TYPE_FIELD_ID): new MultichoiceMapField(rawValue: ["server"]), + ] as Map>)) + assert outcome != null + assert outcome.case.dataSet.get(VALIDATION_DEFINITION_GROOVY_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_NUM_ARGUMENTS_GROOVY_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_DEFINITION_GROOVY_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_NUM_ARGUMENTS_GROOVY_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_DEFINITION_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).hidden + assert outcome.case.dataSet.get(VALIDATION_NUM_ARGUMENTS_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).hidden + assert outcome.case.dataSet.get(VALIDATION_DEFINITION_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).hidden + assert outcome.case.dataSet.get(VALIDATION_NUM_ARGUMENTS_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).hidden + + outcome = importHelper.setTaskData("Init", validationCase.stringId, new DataSet([ + (VALIDATION_VALIDATION_TYPE_FIELD_ID): new MultichoiceMapField(rawValue: ["server", "client"]), + ] as Map>)) + assert outcome != null + assert outcome.case.dataSet.get(VALIDATION_DEFINITION_GROOVY_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_NUM_ARGUMENTS_GROOVY_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_DEFINITION_GROOVY_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_NUM_ARGUMENTS_GROOVY_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_DEFINITION_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_NUM_ARGUMENTS_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_INIT_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_DEFINITION_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).editable + assert outcome.case.dataSet.get(VALIDATION_NUM_ARGUMENTS_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).editable + + outcome = importHelper.setTaskData("Init", validationCase.stringId, new DataSet([ + (VALIDATION_NAME_FIELD_ID): new TextField(rawValue: "test"), + (VALIDATION_VALIDATION_TYPE_FIELD_ID): new MultichoiceMapField(rawValue: ["server"]), + (VALIDATION_DEFINITION_GROOVY_FIELD_ID): new TextField(rawValue: "-> field.rawValue == 1") + ] as Map>)) + assert outcome != null + + validationTask = importHelper.finishTaskAsSuper("Init", validationCase.stringId).getTask() + assert validationTask != null + + validationTask = importHelper.assignTaskToSuper("Activate", validationCase.stringId).getTask() + assert validationTask != null + + validationTask = importHelper.finishTaskAsSuper("Activate", validationCase.stringId).getTask() + assert validationTask != null + + validationCase = workflowService.findOne(validationCase.stringId) + + assert validationCase.dataSet.get(VALIDATION_DEFINITION_GROOVY_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).visible + assert validationCase.dataSet.get(VALIDATION_NUM_ARGUMENTS_GROOVY_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).visible + assert validationCase.dataSet.get(VALIDATION_DEFINITION_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).hidden + assert validationCase.dataSet.get(VALIDATION_NUM_ARGUMENTS_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).hidden + + validationTask = importHelper.assignTaskToSuper("Deactivate", validationCase.stringId).getTask() + assert validationTask != null + + validationTask = importHelper.finishTaskAsSuper("Deactivate", validationCase.stringId).getTask() + assert validationTask != null + + validationCase = workflowService.findOne(validationCase.stringId) + + assert validationCase.dataSet.get(VALIDATION_DEFINITION_GROOVY_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).editable + assert validationCase.dataSet.get(VALIDATION_NUM_ARGUMENTS_GROOVY_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).editable + assert validationCase.dataSet.get(VALIDATION_DEFINITION_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).hidden + assert validationCase.dataSet.get(VALIDATION_NUM_ARGUMENTS_JAVASCRIPT_FIELD_ID).behaviors.get(VALIDATION_DETAIL_TRANS_ID).hidden + } + + @Test + void dynamicValidation_process_create() { + Process net = petriNetService.getNewestVersionByIdentifier(VALIDATION_PETRI_NET_IDENTIFIER) + + Case validationCase = importHelper.createCase("Validation test", net) + assert validationCase != null + + Task validationTask = importHelper.assignTaskToSuper("Init", validationCase.stringId).getTask() + assert validationTask != null + + SetDataEventOutcome outcome = importHelper.setTaskData("Init", validationCase.stringId, new DataSet([ + (VALIDATION_NAME_FIELD_ID): new TextField(rawValue: "test"), + (VALIDATION_VALIDATION_TYPE_FIELD_ID): new MultichoiceMapField(rawValue: ["server"]), + (VALIDATION_DEFINITION_GROOVY_FIELD_ID): new TextField(rawValue: null) + ] as Map>)) + assert outcome != null + + validationTask = importHelper.finishTaskAsSuper("Init", validationCase.stringId).getTask() + assert validationTask != null + + validationTask = importHelper.assignTaskToSuper("Activate", validationCase.stringId).getTask() + assert validationTask != null + + Assertions.assertThrows(IllegalArgumentException.class, () -> { + validationTask = importHelper.finishTaskAsSuper("Activate", validationCase.stringId).getTask() + assert validationTask != null + }) + + outcome = importHelper.setTaskData("Detail", validationCase.stringId, new DataSet([ + (VALIDATION_DEFINITION_GROOVY_FIELD_ID): new TextField(rawValue: "-> field.rawValue == 1") + ] as Map>)) + assert outcome != null + + validationTask = importHelper.finishTaskAsSuper("Activate", validationCase.stringId).getTask() + assert validationTask != null + } +} diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/ChangedFieldsAllowedNetsTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/ChangedFieldsAllowedNetsTest.groovy index 2cb5c434987..c088acc017d 100644 --- a/src/test/groovy/com/netgrif/application/engine/workflow/ChangedFieldsAllowedNetsTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/workflow/ChangedFieldsAllowedNetsTest.groovy @@ -1,10 +1,9 @@ package com.netgrif.application.engine.workflow import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.workflow.domain.eventoutcomes.EventOutcome -import com.netgrif.application.engine.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome +import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.service.interfaces.IDataService import groovy.transform.CompileStatic import org.junit.jupiter.api.BeforeEach @@ -41,7 +40,10 @@ class ChangedFieldsAllowedNetsTest { @Autowired private TestHelper testHelper - private PetriNet net + @Autowired + private SuperCreator superCreator + + private Process net @BeforeEach void beforeAll() { @@ -49,6 +51,8 @@ class ChangedFieldsAllowedNetsTest { def netOptional = importHelper.createNet("changed_fields_allowed_nets.xml") assert netOptional.isPresent() net = netOptional.get() + + TestHelper.login(superCreator.superIdentity) } // NAE-1374 diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/DataServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/DataServiceTest.groovy index e03ce2136cf..f18b6829b31 100644 --- a/src/test/groovy/com/netgrif/application/engine/workflow/DataServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/workflow/DataServiceTest.groovy @@ -2,24 +2,16 @@ package com.netgrif.application.engine.workflow import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.petrinet.domain.DataGroup -import com.netgrif.application.engine.petrinet.domain.DataRef -import com.netgrif.application.engine.petrinet.domain.PetriNet -import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import groovy.transform.CompileStatic -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest -import org.springframework.mock.web.MockMultipartFile import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension @@ -29,9 +21,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension @CompileStatic class DataServiceTest { - private static final String TASK_TITLE = "Transition"; - private static final String FILE_FIELD_TITLE = "File"; - private static final String TEXT_FIELD_TITLE = "Result"; + private static final String TASK_TITLE = "Transition" + private static final String FILE_FIELD_TITLE = "File" + private static final String TEXT_FIELD_TITLE = "Result" @Autowired private ImportHelper importHelper @@ -51,74 +43,75 @@ class DataServiceTest { @Autowired private IWorkflowService workflowService - private PetriNet agreementNet - private PetriNet setDataNet - private PetriNet net + private Process agreementNet + private Process setDataNet + private Process net - @BeforeEach - void beforeAll() { - testHelper.truncateDbs() - ImportPetriNetEventOutcome net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/data_service_referenced.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null - - net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/data_service_taskref.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null - this.net = net.getNet() - - ImportPetriNetEventOutcome agreementNet = petriNetService.importPetriNet(new FileInputStream("src/test/resources/agreement.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert agreementNet.getNet() != null - this.agreementNet = agreementNet.getNet() - - ImportPetriNetEventOutcome netoutcome = petriNetService.importPetriNet(new FileInputStream("src/test/resources/test_setData.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - assert netoutcome.getNet() != null; - this.setDataNet = netoutcome.getNet(); - } - - @Test - @Disabled - void testTaskrefedFileFieldAction() { - def aCase = importHelper.createCase("Case", this.net) - assert aCase != null - - def taskId = importHelper.getTaskId(TASK_TITLE, aCase.stringId) - assert taskId != null - - importHelper.assignTaskToSuper(TASK_TITLE, aCase.stringId) - List datagroups = dataService.getDataGroups(taskId, Locale.ENGLISH, superCreator.getLoggedSuper()).getData() - - assert datagroups.stream().filter({ it -> it.dataRefs.size() > 0 }).count() == 3 - DataRef fileField = findField(datagroups, FILE_FIELD_TITLE) - MockMultipartFile file = new MockMultipartFile("data", "filename.txt", "text/plain", "hello world".getBytes()) - def changes = dataService.saveFile(taskId, fileField.fieldId, file) - assert changes.changedFields.fields.size() == 1 - DataRef textField = findField(datagroups, TEXT_FIELD_TITLE) - assert changes.changedFields.fields.containsKey(textField.fieldId) - assert changes.changedFields.fields.get(textField.fieldId).rawValue == "OK" - } - - DataRef findField(List datagroups, String fieldTitle) { - def fieldDataGroup = datagroups.find { it -> it.dataRefs.values().find({ DataRef field -> (field.field.name.defaultValue == fieldTitle) }) != null } - assert fieldDataGroup != null - DataRef field = fieldDataGroup.dataRefs.values().find({ DataRef field -> (field.field.name.defaultValue == fieldTitle) }) - assert field != null - return field - } - - @Test - void testTaskRefOrderOnGridLayout() { - def aCase = importHelper.createCase("Case", this.agreementNet) - assert aCase != null - - def taskId = importHelper.getTaskId("summary A", aCase.stringId) - assert taskId != null - - importHelper.assignTaskToSuper("summary A", aCase.stringId) + // TODO: release/8.0.0 +// @BeforeEach +// void beforeAll() { +// testHelper.truncateDbs() +// ImportPetriNetEventOutcome net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/data_service_referenced.xml"), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId()) +// assert net.getNet() != null +// +// net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/data_service_taskref.xml"), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId()) +// assert net.getNet() != null +// this.net = net.getNet() +// +// ImportPetriNetEventOutcome agreementNet = petriNetService.importPetriNet(new FileInputStream("src/test/resources/agreement.xml"), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId()) +// assert agreementNet.getNet() != null +// this.agreementNet = agreementNet.getNet() +// +// ImportPetriNetEventOutcome netoutcome = petriNetService.importPetriNet(new FileInputStream("src/test/resources/test_setData.xml"), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId()); +// assert netoutcome.getNet() != null; +// this.setDataNet = netoutcome.getNet(); +// } - List dataGroups = dataService.getDataGroups(taskId, Locale.ENGLISH, superCreator.getLoggedSuper()).getData() - assert dataGroups.get(1).getParentTaskRefId() == "taskRef_result" - assert dataGroups.get(2).getParentTaskRefId() == "taskRef_1" - assert dataGroups.get(3).getParentTaskRefId() == "taskRef_0" - } +// @Test +// @Disabled +// void testTaskrefedFileFieldAction() { +// def aCase = importHelper.createCase("Case", this.net) +// assert aCase != null +// +// def taskId = importHelper.getTaskId(TASK_TITLE, aCase.stringId) +// assert taskId != null +// +// importHelper.assignTaskToSuper(TASK_TITLE, aCase.stringId) +// List datagroups = dataService.getLayouts(taskId, Locale.ENGLISH, superCreator.getLoggedSuper().getActiveActorId()).getData() +// +// assert datagroups.stream().filter({ it -> it.dataRefs.size() > 0 }).count() == 3 +// DataRef fileField = findField(datagroups, FILE_FIELD_TITLE) +// MockMultipartFile file = new MockMultipartFile("data", "filename.txt", "text/plain", "hello world".getBytes()) +// def changes = dataService.saveFile(taskId, fileField.fieldId, file) +// assert changes.changedFields.fields.size() == 1 +// DataRef textField = findField(datagroups, TEXT_FIELD_TITLE) +// assert changes.changedFields.fields.containsKey(textField.fieldId) +// assert changes.changedFields.fields.get(textField.fieldId).rawValue == "OK" +// } +// +// DataRef findField(List datagroups, String fieldTitle) { +// def fieldDataGroup = datagroups.find { it -> it.dataRefs.values().find({ DataRef field -> (field.field.name.defaultValue == fieldTitle) }) != null } +// assert fieldDataGroup != null +// DataRef field = fieldDataGroup.dataRefs.values().find({ DataRef field -> (field.field.name.defaultValue == fieldTitle) }) +// assert field != null +// return field +// } +// +// @Test +// void testTaskRefOrderOnGridLayout() { +// def aCase = importHelper.createCase("Case", this.agreementNet) +// assert aCase != null +// +// def taskId = importHelper.getTaskId("summary A", aCase.stringId) +// assert taskId != null +// +// importHelper.assignTaskToSuper("summary A", aCase.stringId) +// +// List dataGroups = dataService.getLayouts(taskId, Locale.ENGLISH, superCreator.getLoggedSuper().getActiveActorId()).getData() +// assert dataGroups.get(1).getParentTaskRefId() == "taskRef_result" +// assert dataGroups.get(2).getParentTaskRefId() == "taskRef_1" +// assert dataGroups.get(3).getParentTaskRefId() == "taskRef_0" +// } // @Test // void testSetDataAllowednets() { diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/InitValuesTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/InitValuesTest.groovy new file mode 100644 index 00000000000..a20e1746d11 --- /dev/null +++ b/src/test/groovy/com/netgrif/application/engine/workflow/InitValuesTest.groovy @@ -0,0 +1,48 @@ +package com.netgrif.application.engine.workflow + +import com.netgrif.application.engine.EngineTest +import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.petrinet.domain.dataset.Field +import org.junit.Assert +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.context.junit.jupiter.SpringExtension + +@SpringBootTest +@ActiveProfiles(["test"]) +@ExtendWith(SpringExtension.class) +class InitValuesTest extends EngineTest { + + @Test + void testInitValues() { + TestHelper.login(superCreator.superIdentity) + + def importResult = importHelper.createNet("init_values_test.xml") + assert importResult.isPresent() + + def net = importResult.get() + def createCase = importHelper.createCase("Test case", net) + assert createCase + + def staticFieldIds = createCase.dataSet.fields.keySet().findAll { it.endsWith("_static") } + def dynamicFieldIds = createCase.dataSet.fields.keySet().findAll { it.endsWith("_dynamic") } + staticFieldIds.each { staticId -> + def id = staticId.replace("_static", "") + Field staticInitField = createCase.dataSet.get("${id}_static") + Field dynamicInitField = createCase.dataSet.get("${id}_dynamic") + dynamicFieldIds.remove(dynamicInitField.importId) + + assert staticInitField.rawValue == dynamicInitField.rawValue && staticInitField.rawValue != null + } + dynamicFieldIds.each { dynamicId -> + Field dynamicInitField = createCase.dataSet.get(dynamicId) + + Assert.assertTrue(dynamicId, dynamicInitField.rawValue != null) + if (dynamicInitField.rawValue instanceof Collection) { + Assert.assertFalse(dynamicId, (dynamicInitField.rawValue as Collection).isEmpty()) + } + } + } +} diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/NewInitTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/NewInitTest.groovy index 9ab1c690868..e43e78d0234 100644 --- a/src/test/groovy/com/netgrif/application/engine/workflow/NewInitTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/workflow/NewInitTest.groovy @@ -2,10 +2,8 @@ package com.netgrif.application.engine.workflow import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException -import com.netgrif.application.engine.petrinet.domain.I18nString import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.dataset.FileFieldValue -import com.netgrif.application.engine.petrinet.domain.dataset.FileListFieldValue +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.SuperCreator @@ -41,13 +39,14 @@ class NewInitTest { @BeforeEach void before() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void newInitTest() throws IOException, MissingIconKeyException, MissingPetriNetMetaDataException { - petriNetService.importPetriNet(new FileInputStream("src/test/resources/petriNets/nae_1276_Init_value_as_choice.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - Case initTestCase = workflowService.createCase(petriNetService.getNewestVersionByIdentifier("new_init_test").stringId, "New init test", "", superCreator.getLoggedSuper()).getCase() + petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/petriNets/nae_1276_Init_value_as_choice.xml"), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) // TODO: release/8.0.0 +// Case initTestCase = workflowService.createCase(petriNetService.getNewestVersionByIdentifier("new_init_test").stringId, "New init test", "", superCreator.getLoggedSuper().getActiveActorId()).getCase() // assert (initTestCase.dataSet["new_init_multichoice"].value as List).stream().any { ((I18nString) it).defaultValue == "Bob" } // assert (initTestCase.dataSet["new_init_multichoice"].value as List).stream().any { ((I18nString) it).defaultValue == "Alice" } // assert (initTestCase.dataSet["old_init_multichoice"].value as List).stream().any { ((I18nString) it).defaultValue == "Bob" } diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/SetDataOnButtonTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/SetDataOnButtonTest.groovy index 92bd8e54627..a6592aacd8e 100644 --- a/src/test/groovy/com/netgrif/application/engine/workflow/SetDataOnButtonTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/workflow/SetDataOnButtonTest.groovy @@ -1,22 +1,18 @@ package com.netgrif.application.engine.workflow import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.petrinet.domain.PetriNet + +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.dataset.ButtonField -import com.netgrif.application.engine.petrinet.domain.dataset.Field import com.netgrif.application.engine.petrinet.domain.dataset.TextField +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.QTask -import com.netgrif.application.engine.workflow.domain.Task import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService -import com.netgrif.application.engine.workflow.web.responsebodies.DataSet import groovy.transform.CompileStatic import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -47,9 +43,6 @@ class SetDataOnButtonTest { @Autowired private IPetriNetService petriNetService - @Autowired - private IUserService userService - @Autowired private TestHelper testHelper @@ -71,13 +64,16 @@ class SetDataOnButtonTest { String TEST_TRANSITION = "t1" String RESOURCE_PATH = "src/test/resources/button_set_data_test.xml" - PetriNet net = null + Process net = null @BeforeEach void initNet() { testHelper.truncateDbs() - net = petriNetService.importPetriNet(new FileInputStream(RESOURCE_PATH), VersionType.MAJOR, userService.loggedOrSystem.transformToLoggedUser()).getNet() + net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream(RESOURCE_PATH), VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() assert net != null + + TestHelper.login(superCreator.superIdentity) } @Test @@ -88,37 +84,39 @@ class SetDataOnButtonTest { assert parentCase.dataSet.get(CHILD_CASE_FIELD_ID).rawValue == childCase.getStringId() workflowService.save(parentCase) - Task parentTask = taskService.searchOne(QTask.task.caseTitle.eq(PARENT_CASE) & QTask.task.transitionId.eq(TEST_TRANSITION)) - assert parentTask != null - - taskService.assignTask(parentTask.getStringId()) - taskService.finishTask(parentTask.getStringId()) - - childCase = workflowService.findOne(childCase.getStringId()) - assert childCase.dataSet.get(TEXT_0_FIELD_ID).rawValue.toString() == OUTPUT_TEXT_0 - assert childCase.dataSet.get(TEXT_1_FIELD_ID).rawValue.toString() == OUTPUT_TEXT_1 - assert childCase.dataSet.get(TEXT_2_FIELD_ID).rawValue.toString() == OUTPUT_TEXT_2 +// TODO: release/8.0.0 +// Task parentTask = taskService.searchOne(QTask.task.caseTitle.eq(PARENT_CASE) & QTask.task.transitionId.eq(TEST_TRANSITION)) +// assert parentTask != null +// +// taskService.assignTask(parentTask.getStringId()) +// taskService.finishTask(parentTask.getStringId()) +// +// childCase = workflowService.findOne(childCase.getStringId()) +// assert childCase.dataSet.get(TEXT_0_FIELD_ID).rawValue.toString() == OUTPUT_TEXT_0 +// assert childCase.dataSet.get(TEXT_1_FIELD_ID).rawValue.toString() == OUTPUT_TEXT_1 +// assert childCase.dataSet.get(TEXT_2_FIELD_ID).rawValue.toString() == OUTPUT_TEXT_2 } @Test void setData() { Case testCase = helper.createCase(PARENT_CASE, net) - Task testCaseTask = taskService.searchOne(QTask.task.caseTitle.eq(PARENT_CASE) & QTask.task.transitionId.eq(TEST_TRANSITION)) - assert testCaseTask != null - dataService.setData(testCaseTask.stringId, new DataSet([ - "button_0": new ButtonField(rawValue: 42), - "button_1": new ButtonField(rawValue: 42), - "button_2": new ButtonField(rawValue: 42) - ] as Map>), superCreator.getLoggedSuper()) - - testCase = workflowService.findOne(testCase.getStringId()) - - assert testCase.dataSet.get(BUTTON_0_FIELD_ID).rawValue == 42 - assert testCase.dataSet.get(BUTTON_1_FIELD_ID).rawValue == 42 - assert testCase.dataSet.get(BUTTON_2_FIELD_ID).rawValue == 42 - assert testCase.dataSet.get(TEXT_0_FIELD_ID).rawValue.toString() == OUTPUT_TEXT_0 - assert testCase.dataSet.get(TEXT_1_FIELD_ID).rawValue.toString() == OUTPUT_TEXT_1 - assert testCase.dataSet.get(TEXT_2_FIELD_ID).rawValue.toString() == OUTPUT_TEXT_2 +// TODO: release/8.0.0 +// Task testCaseTask = taskService.searchOne(QTask.task.caseTitle.eq(PARENT_CASE) & QTask.task.transitionId.eq(TEST_TRANSITION)) +// assert testCaseTask != null +// dataService.setData(testCaseTask.stringId, new DataSet([ +// "button_0": new ButtonField(rawValue: 42), +// "button_1": new ButtonField(rawValue: 42), +// "button_2": new ButtonField(rawValue: 42) +// ] as Map>), superCreator.getLoggedSuper().getActiveActorId()) +// +// testCase = workflowService.findOne(testCase.getStringId()) +// +// assert testCase.dataSet.get(BUTTON_0_FIELD_ID).rawValue == 42 +// assert testCase.dataSet.get(BUTTON_1_FIELD_ID).rawValue == 42 +// assert testCase.dataSet.get(BUTTON_2_FIELD_ID).rawValue == 42 +// assert testCase.dataSet.get(TEXT_0_FIELD_ID).rawValue.toString() == OUTPUT_TEXT_0 +// assert testCase.dataSet.get(TEXT_1_FIELD_ID).rawValue.toString() == OUTPUT_TEXT_1 +// assert testCase.dataSet.get(TEXT_2_FIELD_ID).rawValue.toString() == OUTPUT_TEXT_2 } } diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy index 7d8395ed397..f47d3b72851 100644 --- a/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy @@ -1,21 +1,17 @@ package com.netgrif.application.engine.workflow import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService -import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.domain.params.IdentityParams +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService +import com.netgrif.application.engine.authorization.domain.Role import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.dataset.Field import com.netgrif.application.engine.petrinet.domain.dataset.FileListFieldValue -import com.netgrif.application.engine.petrinet.domain.dataset.UserListField -import com.netgrif.application.engine.petrinet.domain.dataset.UserListFieldValue -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.petrinet.domain.dataset.TextField import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.utils.FullPageRequest @@ -28,7 +24,6 @@ import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowServi import com.netgrif.application.engine.workflow.web.TaskController import com.netgrif.application.engine.workflow.web.WorkflowController import com.netgrif.application.engine.workflow.web.requestbodies.TaskSearchRequest -import com.netgrif.application.engine.workflow.web.responsebodies.DataSet import com.netgrif.application.engine.workflow.web.responsebodies.TaskReference import groovy.transform.CompileStatic import org.junit.jupiter.api.BeforeEach @@ -62,14 +57,11 @@ class TaskControllerTest { private WorkflowController workflowController @Autowired - private IProcessRoleService processRoleService + private IRoleService roleService @Autowired private IDataService dataService - @Autowired - private IUserService userService - @Autowired private IPetriNetService petriNetService @@ -83,34 +75,35 @@ class TaskControllerTest { private ImportHelper helper @Autowired - private IAuthorityService authorityService + private IWorkflowService workflowService @Autowired - private IWorkflowService workflowService + private IIdentityService identityService @Autowired private TaskController taskController - private PetriNet net + private Process net private Case useCase - private ProcessRole role + private Role role private Task task + private Identity testIdentity + @BeforeEach void init() { testHelper.truncateDbs() - userService.saveNew(new User( - name: "Dummy", - surname: "Netgrif", - email: DUMMY_USER_MAIL, - password: "superAdminPassword", - state: UserState.ACTIVE, - authorities: [authorityService.getOrCreate(Authority.user)] as Set, - processRoles: [] as Set)) + testIdentity = helper.createIdentity(IdentityParams.with() + .firstname(new TextField("Dummy")) + .lastname(new TextField("Netgrif")) + .username(new TextField(DUMMY_USER_MAIL)) + .password(new TextField("superAdminPassword")) + .build(), new ArrayList()) importNet() + TestHelper.login(superCreator.superIdentity) } @Test @@ -123,7 +116,7 @@ class TaskControllerTest { @Test void testDeleteFile() { Case testCase = helper.createCase("My case", net) - String taskId = testCase.getTaskStringId("1") + String taskId = testCase.getTaskStringId("t1") // TODO: release/8.0.0 // java.lang.NullPointerException: Cannot invoke "com.netgrif.application.engine.petrinet.domain.dataset.FileFieldValue.getName()" because the return value of "com.netgrif.application.engine.workflow.domain.DataFieldValue.getValue()" is null @@ -139,7 +132,7 @@ class TaskControllerTest { @Test void testDeleteFileByName() { Case testCase = helper.createCase("My case", net) - String taskId = testCase.getTaskStringId( "1") + String taskId = testCase.getTaskStringId( "t1") dataService.saveFiles(taskId, "fileList", new MockMultipartFile[]{new MockMultipartFile("test", "test", null, new byte[]{})}) testCase = workflowService.findOne(testCase.stringId) @@ -155,14 +148,14 @@ class TaskControllerTest { createCase() findTask() setUserListValue() - setUserRole() + setActorRole() assert !findTasksByMongo().empty } void testWithRole() { createCase() findTask() - setUserRole() + setActorRole() assert !findTasksByMongo().empty } @@ -174,7 +167,7 @@ class TaskControllerTest { } void importNet() { - PetriNet netOptional = helper.createNet("all_data_refs.xml", VersionType.MAJOR).get() + Process netOptional = helper.createNet("all_data_refs.xml", VersionType.MAJOR).get() assert netOptional != null net = netOptional } @@ -185,6 +178,15 @@ class TaskControllerTest { assert useCase != null } + void setUserListValue() { + assert task != null + // TODO: release/8.0.0 field 'performable_users' does not exist +// String userId = userService.findByEmail(DUMMY_USER_MAIL).getStringId() +// dataService.setData(task.stringId, new DataSet([ +// "performable_users": new UserListField(rawValue: new UserListFieldValue(dataService.makeUserFieldValue(userId))) +// ] as Map>)) + } + void findTask() { List taskReferences = taskService.findAllByCase(useCase.stringId, new Locale("en")) assert taskReferences.size() > 0 @@ -196,30 +198,16 @@ class TaskControllerTest { assert task != null } - void setUserListValue() { - assert task != null - String userId = userService.findByEmail(DUMMY_USER_MAIL).getStringId() - // TODO: release/8.0.0 field 'performable_users' does not exist -// dataService.setData(task.stringId, new DataSet([ -// "performable_users": new UserListField(rawValue: new UserListFieldValue(dataService.makeUserFieldValue(userId))) -// ] as Map>)) - } - - void setUserRole() { - List roles = processRoleService.findAll(net.stringId) - - for (ProcessRole role : roles) { - if (role.importId == "process_role") { - this.role = role - } - } - processRoleService.assignRolesToUser(userService.findByEmail(DUMMY_USER_MAIL).getStringId(), [role.id.toString()] as Set, userService.getLoggedOrSystem().transformToLoggedUser()) + void setActorRole() { + this.role = roleService.findProcessRoleByImportId("process_role") + roleService.assignRolesToActor(testIdentity.toSession().activeActorId, [role.id.toString()] as Set) } Page findTasksByMongo() { List taskSearchRequestList = new ArrayList<>() taskSearchRequestList.add(new TaskSearchRequest()) - Page tasks = taskService.search(taskSearchRequestList, new FullPageRequest(), userService.findByEmail(DUMMY_USER_MAIL).transformToLoggedUser(), new Locale("en"), false) + String actorId = testIdentity.toSession().activeActorId + Page tasks = taskService.search(taskSearchRequestList, new FullPageRequest(), actorId, new Locale("en"), false) return tasks } } diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/TaskRefInitTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/TaskRefInitTest.groovy index 3ee198fa4ff..71f9f6a3d27 100644 --- a/src/test/groovy/com/netgrif/application/engine/workflow/TaskRefInitTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/workflow/TaskRefInitTest.groovy @@ -1,12 +1,14 @@ package com.netgrif.application.engine.workflow import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService -import com.netgrif.application.engine.petrinet.domain.PetriNet + +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.dataset.TaskField +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper +import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.QTask import com.netgrif.application.engine.workflow.domain.Task @@ -36,38 +38,43 @@ class TaskRefInitTest { private IPetriNetService petriNetService @Autowired - private IUserService userService + private TestHelper testHelper @Autowired - private TestHelper testHelper + private SuperCreator superCreator - PetriNet net = null - PetriNet autoTrigger = null + Process net = null + Process autoTrigger = null @BeforeEach void initNet() { testHelper.truncateDbs() - net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/taskref_init.xml"), VersionType.MAJOR, userService.loggedOrSystem.transformToLoggedUser()).getNet() - autoTrigger = petriNetService.importPetriNet(new FileInputStream("src/test/resources/autotrigger_taskref.xml"), VersionType.MAJOR, userService.loggedOrSystem.transformToLoggedUser()).getNet() + net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/taskref_init.xml"), VersionType.MAJOR, + superCreator.getLoggedSuper().activeActorId)).getProcess() + autoTrigger = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/autotrigger_taskref.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)).getProcess() assert net != null + + TestHelper.login(superCreator.superIdentity) } @Test void testInitValue() { Case aCase = helper.createCase("Test task ref init", net) - Task task1 = taskService.searchOne(QTask.task.caseTitle.eq("Test task ref init") & QTask.task.transitionId.eq("t1")) - Task task2 = taskService.searchOne(QTask.task.caseTitle.eq("Test task ref init") & QTask.task.transitionId.eq("t2")) - Task task3 = taskService.searchOne(QTask.task.caseTitle.eq("Test task ref init") & QTask.task.transitionId.eq("t3")) - List taskref_0_values = ((TaskField)aCase.dataSet.get("taskRef_0")).rawValue - List taskref_1_values = ((TaskField)aCase.dataSet.get("taskRef_1")).rawValue - List taskref_2_values = ((TaskField)aCase.dataSet.get("taskRef_2")).rawValue - List taskref_3_values = ((TaskField)aCase.dataSet.get("taskRef_3")).rawValue + Task task1 = taskService.searchOne(QTask.task.caseId.eq(aCase.stringId) & QTask.task.transitionId.eq("t1")) + Task task2 = taskService.searchOne(QTask.task.caseId.eq(aCase.stringId) & QTask.task.transitionId.eq("t2")) + Task task3 = taskService.searchOne(QTask.task.caseId.eq(aCase.stringId) & QTask.task.transitionId.eq("t3")) + + List taskref_0_values = ((TaskField) aCase.dataSet.get("taskRef_0")).rawValue + List taskref_1_values = ((TaskField) aCase.dataSet.get("taskRef_1")).rawValue + List taskref_2_values = ((TaskField) aCase.dataSet.get("taskRef_2")).rawValue + List taskref_3_values = ((TaskField) aCase.dataSet.get("taskRef_3")).rawValue assert taskref_0_values.containsAll([task1.stringId, task3.stringId]) && taskref_0_values.size() == 2 assert taskref_1_values.containsAll([task2.stringId]) && taskref_1_values.size() == 1 assert taskref_2_values.containsAll([task1.stringId, task2.stringId]) && taskref_2_values.size() == 2 - assert taskref_3_values.empty + assert taskref_3_values == null } @Test diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/TaskRefPropagationTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/TaskRefPropagationTest.groovy index f1f817e4cb7..147134edffd 100644 --- a/src/test/groovy/com/netgrif/application/engine/workflow/TaskRefPropagationTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/workflow/TaskRefPropagationTest.groovy @@ -1,8 +1,9 @@ package com.netgrif.application.engine.workflow -import com.netgrif.application.engine.petrinet.domain.DataGroup -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator @@ -43,19 +44,24 @@ class TaskRefPropagationTest { @Autowired private ITaskService taskService - PetriNet netParent - PetriNet netChild + @Autowired + private TestHelper testHelper + + Process netParent + Process netChild @BeforeEach void beforeAll() { - def parent = petriNetService.importPetriNet(new FileInputStream("src/test/resources/taskRef_propagation_test_parent.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - def child = petriNetService.importPetriNet(new FileInputStream("src/test/resources/taskRef_propagation_test_child.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) + def parent = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/taskRef_propagation_test_parent.xml"), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + def child = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/taskRef_propagation_test_child.xml"), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + + assert parent.getProcess() != null + assert child.getProcess() != null - assert parent.getNet() != null - assert child.getNet() != null + netParent = parent.getProcess() + netChild = child.getProcess() - netParent = parent.getNet() - netChild = child.getNet() + TestHelper.login(superCreator.superIdentity) } public static final String PARENT_FIELD_TEXT_ID = "text" @@ -97,8 +103,8 @@ class TaskRefPropagationTest { Case parent = importHelper.createCase("PARENT", netParent) Case child = importHelper.createCase("CHILD", netChild) - String parentTaskId = parent.getTaskStringId("4") - String childTaskId = child.getTaskStringId("4") + String parentTaskId = parent.getTaskStringId("t4") + String childTaskId = child.getTaskStringId("t4") // TODO: release/8.0.0 // parent.dataSet["children_tasks"].value = [childTaskId] // child.dataSet["parentId"].value = parent.stringId @@ -107,7 +113,8 @@ class TaskRefPropagationTest { workflowService.save(child) /* validate getDataGroups object and taskRef field ids */ - List parentData = dataService.getDataGroups(parentTaskId, Locale.forLanguageTag("SK"), superCreator.getLoggedSuper()).data + // TODO: NAE-1969 fix +// List parentData = dataService.getDataGroups(parentTaskId, Locale.forLanguageTag("SK"), superCreator.getLoggedSuper().getActiveActorId()).data // TODO: release/8.0.0 fix // LocalisedField parentText = findField(parentData, PARENT_FIELD_TEXT_TITLE) // LocalisedField parentMultichoice = findField(parentData, PARENT_FIELD_MULTICHOICE_TITLE) diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/TaskStateTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/TaskStateTest.groovy index fb997411a3b..b77c45fd60a 100644 --- a/src/test/groovy/com/netgrif/application/engine/workflow/TaskStateTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/workflow/TaskStateTest.groovy @@ -2,14 +2,17 @@ package com.netgrif.application.engine.workflow import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.importer.service.AllDataConfiguration -import com.netgrif.application.engine.petrinet.domain.PetriNet +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case import com.netgrif.application.engine.workflow.domain.Task +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams +import com.netgrif.application.engine.workflow.domain.params.TaskParams import com.netgrif.application.engine.workflow.service.interfaces.ITaskService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import groovy.transform.CompileStatic +import org.junit.Assert import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -43,20 +46,26 @@ class TaskStateTest { @BeforeEach void setup() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void testTaskState() { def netOptional = importHelper.createNet("NAE-1858_task_state.xml") assert netOptional.isPresent() - PetriNet net = netOptional.get() + Process net = netOptional.get() - Case useCase = workflowService.createCase(net.stringId, "Test Case", "", superCreator.superUser.transformToLoggedUser())?.case + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Test Case") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case useCase = workflowService.createCase(createCaseParams)?.case assert useCase List tasks = taskService.findAllByCase(useCase.stringId) tasks.each { task -> - assert (task.title as String) == "N" ? task.state == DISABLED : task.state == ENABLED + Assert.assertTrue(task.transitionId, (task.title as String) == "N" ? task.state == DISABLED : task.state == ENABLED) } } @@ -64,24 +73,29 @@ class TaskStateTest { void testTaskState2() { def netOptional = importHelper.createNet("NAE-1858_task_state_2.xml") assert netOptional.isPresent() - PetriNet net = netOptional.get() + Process net = netOptional.get() - Case useCase = workflowService.createCase(net.stringId, "Test Case", "", superCreator.superUser.transformToLoggedUser())?.case + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Test Case") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case useCase = workflowService.createCase(createCaseParams)?.case assert useCase 4.times { index -> List tasks = taskService.findAllByCase(useCase.stringId) String transitionId = "t${index + 1}" - tasks.each { t-> + tasks.each { t -> assert t.transitionId in [transitionId, allDataConfiguration.allData.id] ? t.state == ENABLED : t.state == DISABLED } - Task task = tasks.find {it.transitionId == transitionId} - taskService.assignTask(task.stringId) + Task task = tasks.find { it.transitionId == transitionId } + taskService.assignTask(new TaskParams(task.stringId)) tasks = taskService.findAllByCase(useCase.stringId) - tasks.each { t-> + tasks.each { t -> assert t.transitionId in [allDataConfiguration.allData.id] ? t.state == ENABLED : t.state == DISABLED } - taskService.finishTask(task.stringId) + taskService.finishTask(new TaskParams(task.stringId)) } } } diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/UserRefsTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/UserRefsTest.groovy index 906bed48de0..86094be72a2 100644 --- a/src/test/groovy/com/netgrif/application/engine/workflow/UserRefsTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/workflow/UserRefsTest.groovy @@ -1,18 +1,20 @@ package com.netgrif.application.engine.workflow import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.authentication.domain.Identity +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService import com.netgrif.application.engine.configuration.properties.SuperAdminConfiguration import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.dataset.Field import com.netgrif.application.engine.petrinet.domain.dataset.UserListField import com.netgrif.application.engine.petrinet.domain.dataset.UserListFieldValue +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import com.netgrif.application.engine.workflow.domain.Case -import com.netgrif.application.engine.workflow.domain.TaskPair +import com.netgrif.application.engine.workflow.domain.params.SetDataParams import com.netgrif.application.engine.workflow.service.interfaces.IDataService import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import com.netgrif.application.engine.workflow.web.responsebodies.DataSet @@ -39,9 +41,6 @@ class UserRefsTest { @Autowired private ImportHelper importHelper - @Autowired - private IUserService userService - @Autowired private IWorkflowService workflowService @@ -57,37 +56,45 @@ class UserRefsTest { @Autowired private SuperCreator superCreator + @Autowired + private IIdentityService identityService + @Autowired private TestHelper helper List newCases - List userIds + List actorIds private String netId @BeforeEach void before() { + // todo release/8.0.0 userList is already tested in RoleServiceTest helper.truncateDbs() - def net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/userrefs_test.xml"), VersionType.MAJOR, userService.loggedOrSystem.transformToLoggedUser()).getNet() + helper.login(superCreator.superIdentity) + def net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/userrefs_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)).getProcess() assert net netId = net.getStringId() def userEmails = [configuration.email, "engine@netgrif.com"] newCases = new ArrayList<>() - userIds = new ArrayList<>() + actorIds = new ArrayList<>() 10.times { def _case = importHelper.createCase("$it" as String, net) - String id = userService.findByEmail(userEmails[it % 2]).getStringId() + Identity identity = identityService.findByUsername(userEmails[it % 2]).get() + String actorId = identity.toSession().activeActorId String taskId = _case.getTaskStringId("t1") - dataService.setData(taskId, new DataSet([ - "user_list_1": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(id)])) - ] as Map>), superCreator.getLoggedSuper()).getCase() - userIds.add(id) + dataService.setData(new SetDataParams(taskId, new DataSet([ + "user_list_1": new UserListField(rawValue: new UserListFieldValue([dataService.makeUserFieldValue(actorId)])) + ] as Map>), superCreator.getLoggedSuper().activeActorId)).getCase() + actorIds.add(actorId) } } @Test void testCases() { - newCases.eachWithIndex { Case entry, int i -> assert entry.users.get(userIds.get(i)) != null } + // TODO: release/8.0.0 fix? +// newCases.eachWithIndex { Case entry, int i -> assert entry.users.get(userIds.get(i)) != null } } } diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/WorkflowServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/WorkflowServiceTest.groovy index 03eee44a48c..02bd6ce8aac 100644 --- a/src/test/groovy/com/netgrif/application/engine/workflow/WorkflowServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/workflow/WorkflowServiceTest.groovy @@ -2,12 +2,16 @@ package com.netgrif.application.engine.workflow import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.ipc.TaskApiTest +import com.netgrif.application.engine.petrinet.domain.Process import com.netgrif.application.engine.petrinet.domain.VersionType +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator -import com.netgrif.application.engine.utils.InputStreamToString import com.netgrif.application.engine.workflow.domain.Case +import com.netgrif.application.engine.workflow.domain.QCase +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams +import com.netgrif.application.engine.workflow.domain.params.DeleteCaseParams import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService import groovy.transform.CompileStatic import org.junit.jupiter.api.BeforeEach @@ -18,6 +22,9 @@ import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension +import static com.netgrif.application.engine.workflow.domain.params.CreateCaseParams.with +import static org.junit.jupiter.api.Assertions.assertThrows + @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @SpringBootTest @@ -27,7 +34,13 @@ class WorkflowServiceTest { public static final String NET_FILE = "case_search_test.xml" public static final String CASE_LOCALE_NET_FILE = "create_case_locale.xml" public static final String FIRST_AUTO_NET_FILE = "petriNets/NAE_1382_first_trans_auto.xml" + public static final String CREATE_CASE_FAILURE_NET_FILE = "create_case_failure.xml" + public static final String DELETE_CASE_FAILURE_NET_FILE = "delete_case_failure.xml" public static final String SECOND_AUTO_NET_FILE = "petriNets/NAE_1382_first_trans_auto_2.xml" + public static final String CHILD_NET_FILE = "importTest/child_extending_parent.xml" + public static final String PARENT_NET_FILE = "importTest/parent_to_be_extended.xml" + public static final String SUPER_PARENT_NET_FILE = "importTest/super_parent_to_be_extended.xml" + @Autowired private ImportHelper importHelper @@ -51,13 +64,15 @@ class WorkflowServiceTest { @BeforeEach void setup() { testHelper.truncateDbs() + TestHelper.login(superCreator.superIdentity) } @Test void testFindOneImmediateData() { - def testNet = petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert testNet.getNet() != null - Case aCase = importHelper.createCase("Case 1", testNet.getNet()) + def testNet = petriNetService.importProcess(new ImportProcessParams(stream(NET_FILE), VersionType.MAJOR, + superCreator.getLoggedSuper().getActiveActorId())) + assert testNet.getProcess() != null + Case aCase = importHelper.createCase("Case 1", testNet.getProcess()) assert aCase.getImmediateData().size() == 5 @@ -69,11 +84,16 @@ class WorkflowServiceTest { @Test void testFirstTransitionAuto() { - def testNet = petriNetService.importPetriNet(stream(FIRST_AUTO_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet() + def testNet = petriNetService.importProcess(new ImportProcessParams(stream(FIRST_AUTO_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() assert testNet def net = testNet - Case aCase = workflowService.createCase(net.stringId, "autoErr", "red", superCreator.getLoggedSuper()).getCase() + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("autoErr") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case aCase = workflowService.createCase(createCaseParams).getCase() importHelper.assignTask("Manual", aCase.getStringId(), superCreator.getLoggedSuper()) importHelper.finishTask("Manual", aCase.getStringId(), superCreator.getLoggedSuper()) @@ -83,9 +103,14 @@ class WorkflowServiceTest { @Test void testSecondTransitionAuto() { - def net = petriNetService.importPetriNet(stream(SECOND_AUTO_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet() + def net = petriNetService.importProcess(new ImportProcessParams(stream(SECOND_AUTO_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess() - Case aCase = workflowService.createCase(net.stringId, "autoErr", "red", superCreator.getLoggedSuper()).getCase() + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("autoErr") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case aCase = workflowService.createCase(createCaseParams).getCase() importHelper.assignTask("Manual", aCase.getStringId(), superCreator.getLoggedSuper()) importHelper.finishTask("Manual", aCase.getStringId(), superCreator.getLoggedSuper()) @@ -98,18 +123,145 @@ class WorkflowServiceTest { @Test void createCaseWithLocale() { - def testNet = petriNetService.importPetriNet(stream(CASE_LOCALE_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert testNet.getNet() != null + def testNet = petriNetService.importProcess(new ImportProcessParams(stream(CASE_LOCALE_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + assert testNet.getProcess() != null - def net = testNet.getNet() - Case aCase = workflowService.createCase(net.stringId, null, null, superCreator.getLoggedSuper(), new Locale('sk')).getCase() + def net = testNet.getProcess() + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .authorId(superCreator.getLoggedSuper().activeActorId) + .locale(new Locale('sk')) + .build() + Case aCase = workflowService.createCase(createCaseParams).getCase() assert aCase.title == "Slovenský preklad" // TODO: release/8.0.0 fix uri nodes // assert workflowService.findOne(aCase.stringId).uriNodeId == net.uriNodeId - Case enCase = workflowService.createCase(net.stringId, null, null, superCreator.getLoggedSuper(), new Locale('en')).getCase() + createCaseParams = CreateCaseParams.with() + .process(net) + .authorId(superCreator.getLoggedSuper().activeActorId) + .locale(new Locale('en')) + .build() + Case enCase = workflowService.createCase(createCaseParams).getCase() assert enCase.title == "English translation" } + + @Test + void createCaseOfExtendedPetriNet() { + Process superParentNet = petriNetService.importProcess(new ImportProcessParams(stream(SUPER_PARENT_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).process + petriNetService.importProcess(new ImportProcessParams(stream(PARENT_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())) + // child extends version 1.1.0 + Process parentNet = petriNetService.importProcess(new ImportProcessParams(stream(PARENT_NET_FILE), VersionType.MINOR, superCreator.getLoggedSuper().getActiveActorId())).process + Process childNet = petriNetService.importProcess(new ImportProcessParams(stream(CHILD_NET_FILE), VersionType.MINOR, superCreator.getLoggedSuper().getActiveActorId())).process + + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(childNet) + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + Case aCase = workflowService.createCase(createCaseParams).getCase() + assert aCase + assert aCase.processIdentifier == childNet.identifier + assert aCase.petriNetObjectId == childNet.objectId + + assert aCase.parentPetriNetIdentifiers.size() == 2 + assert aCase.parentPetriNetIdentifiers.get(0).identifier == superParentNet.identifier + assert aCase.parentPetriNetIdentifiers.get(0).id == superParentNet.objectId + assert aCase.parentPetriNetIdentifiers.get(1).identifier == parentNet.identifier + assert aCase.parentPetriNetIdentifiers.get(1).id == parentNet.objectId + + assert aCase.dataSet.fields.size() == 4 + assert (aCase.dataSet.get("taskref2").value.value as List)[0] == aCase.tasks["t0"].taskId.toString() + } + + @Test + void testTransactionalCreateCaseFailure() { + petriNetService.importProcess(new ImportProcessParams( + stream(CASE_LOCALE_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) + Process process = petriNetService.importProcess(new ImportProcessParams( + stream(CREATE_CASE_FAILURE_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)).getProcess() + + CreateCaseParams createCaseParams = with() + .isTransactional(true) + .process(process) + .title("FailedCase") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + + assertThrows(RuntimeException.class, { workflowService.createCase(createCaseParams) }) + + assert workflowService.searchOne(QCase.case$.title.eq("FailedCase")) == null + assert workflowService.searchOne(QCase.case$.title.eq("CaseFromPre")) == null + assert workflowService.searchOne(QCase.case$.title.eq("CaseFromPost")) == null + } + + @Test + void testNonTransactionalCreateCaseFailure() { + petriNetService.importProcess(new ImportProcessParams( + stream(CASE_LOCALE_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)) + Process process = petriNetService.importProcess(new ImportProcessParams( + stream(CREATE_CASE_FAILURE_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)).getProcess() + + CreateCaseParams createCaseParams = with() + .isTransactional(false) + .process(process) + .title("FailedCase") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + + assertThrows(RuntimeException.class, { workflowService.createCase(createCaseParams) }) + + assert workflowService.searchOne(QCase.case$.title.eq("FailedCase")) != null // failure in post action + assert workflowService.searchOne(QCase.case$.title.eq("CaseFromPre")) != null + assert workflowService.searchOne(QCase.case$.title.eq("CaseFromPost")) != null + } + + @Test + void testTransactionalDeleteCaseFailure() { + Process process = petriNetService.importProcess(new ImportProcessParams( + stream(DELETE_CASE_FAILURE_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)).getProcess() + + CreateCaseParams createCaseParams = with() + .process(process) + .title("CaseToRemove") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + + Case useCase = workflowService.createCase(createCaseParams).getCase() + + DeleteCaseParams deleteCaseParams = DeleteCaseParams.with() + .isTransactional(true) + .useCase(useCase) + .build() + assertThrows(RuntimeException.class, { workflowService.deleteCase(deleteCaseParams) }) + + assert workflowService.searchOne(QCase.case$.title.eq("CaseToRemove")) != null + assert workflowService.searchOne(QCase.case$.title.eq("CaseFromPre")) == null + assert workflowService.searchOne(QCase.case$.title.eq("CaseFromPost")) == null + } + + @Test + void testNonTransactionalDeleteCaseFailure() { + Process process = petriNetService.importProcess(new ImportProcessParams( + stream(DELETE_CASE_FAILURE_NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper().activeActorId)).getProcess() + + CreateCaseParams createCaseParams = with() + .process(process) + .title("CaseToRemove") + .authorId(superCreator.getLoggedSuper().activeActorId) + .build() + + Case useCase = workflowService.createCase(createCaseParams).getCase() + + DeleteCaseParams deleteCaseParams = DeleteCaseParams.with() + .isTransactional(false) + .useCase(useCase) + .build() + assertThrows(RuntimeException.class, { workflowService.deleteCase(deleteCaseParams) }) + + assert workflowService.searchOne(QCase.case$.title.eq("CaseToRemove")) == null // failure in post action + assert workflowService.searchOne(QCase.case$.title.eq("CaseFromPre")) != null + assert workflowService.searchOne(QCase.case$.title.eq("CaseFromPost")) != null + } } diff --git a/src/test/java/com/netgrif/application/engine/MailSenderServiceTest.java b/src/test/java/com/netgrif/application/engine/MailSenderServiceTest.java index b08baa56b01..f2ac2214acf 100644 --- a/src/test/java/com/netgrif/application/engine/MailSenderServiceTest.java +++ b/src/test/java/com/netgrif/application/engine/MailSenderServiceTest.java @@ -2,10 +2,13 @@ import com.icegreen.greenmail.util.GreenMail; import com.icegreen.greenmail.util.ServerSetup; -import com.netgrif.application.engine.auth.domain.User; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; import com.netgrif.application.engine.mail.EmailType; import com.netgrif.application.engine.mail.domain.MailDraft; import com.netgrif.application.engine.mail.interfaces.IMailService; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.startup.ImportHelper; import freemarker.template.TemplateException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -20,6 +23,7 @@ import javax.mail.internet.MimeMessage; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; @SpringBootTest @@ -34,6 +38,9 @@ public class MailSenderServiceTest { @Autowired private IMailService service; + @Autowired + private ImportHelper importHelper; + private GreenMail smtpServer; @BeforeEach @@ -44,7 +51,11 @@ public void before() { @Test public void testSend() throws Exception { - service.sendRegistrationEmail(new User(RECIPIENT, "", "", "")); + Identity identity = importHelper.createIdentity(IdentityParams.with() + .username(new TextField(RECIPIENT)) + .password(new TextField("password")) + .build(), new ArrayList<>()); + service.sendRegistrationEmail(identity); MimeMessage[] messages = smtpServer.getReceivedMessages(); diff --git a/src/test/java/com/netgrif/application/engine/MockService.java b/src/test/java/com/netgrif/application/engine/MockService.java index f3952d90b2d..30705ddc0a6 100644 --- a/src/test/java/com/netgrif/application/engine/MockService.java +++ b/src/test/java/com/netgrif/application/engine/MockService.java @@ -1,28 +1,25 @@ package com.netgrif.application.engine; -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.configuration.properties.SuperAdminConfiguration; import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import java.util.Collections; - @Component @Profile("test") public class MockService { - @Autowired - private IAuthorityService authorityService; - @Autowired private SuperAdminConfiguration configuration; - public LoggedUser mockLoggedUser() { - Authority authorityUser = authorityService.getOrCreate(Authority.user); - return new LoggedUser(new ObjectId().toString(), configuration.getEmail(), configuration.getPassword(), Collections.singleton(authorityUser)); + public LoggedIdentity mockLoggedIdentity() { + return LoggedIdentity.with() + .identityId(new ObjectId().toString()) + .username(configuration.getEmail()) + .password(configuration.getPassword()) + .activeActorId(new ObjectId().toString()) + .build(); } } diff --git a/src/test/java/com/netgrif/application/engine/auth/service/TokenServiceTest.java b/src/test/java/com/netgrif/application/engine/auth/service/TokenServiceTest.java deleted file mode 100644 index a9a57ddf111..00000000000 --- a/src/test/java/com/netgrif/application/engine/auth/service/TokenServiceTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.netgrif.application.engine.auth.service; - -import com.netgrif.application.engine.auth.domain.User; -import com.netgrif.application.engine.auth.domain.UserState; -import com.netgrif.application.engine.auth.domain.repositories.UserRepository; -import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import java.io.ByteArrayOutputStream; -import java.time.LocalDateTime; - -@ExtendWith(SpringExtension.class) -@ActiveProfiles({"test"}) -@SpringBootTest -public class TokenServiceTest { - - private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); - @Autowired - IRegistrationService service; - @Autowired - UserRepository repository; - - @BeforeEach - public void setUp() { - repository.deleteAll(); - } - - @AfterEach - public void cleanUp() { - repository.deleteAll(); - } - - @Test - public void removeExpired() throws Exception { - User expired = new User("test@test.com", null, User.UNKNOWN, User.UNKNOWN); - expired.setToken("token"); - expired.setExpirationDate(LocalDateTime.now().minusDays(10)); - expired.setState(UserState.INVITED); - repository.save(expired); - - User expired2 = new User("test2@test.com", null, User.UNKNOWN, User.UNKNOWN); - expired2.setToken("token2"); - expired2.setState(UserState.INVITED); - repository.save(expired2); - - service.removeExpiredUsers(); - - assert repository.findAll().size() == 1; - } - - @Test - public void authorizeToken() throws Exception { - User expired = new User("test3@test.com", null, User.UNKNOWN, User.UNKNOWN); - expired.setToken("token3"); - expired.setExpirationDate(LocalDateTime.now().plusMinutes(10)); - expired.setState(UserState.INVITED); - repository.save(expired); - - boolean authorized = service.verifyToken(service.encodeToken("test3@test.com", "token3")); - User token = repository.findByEmail("test3@test.com"); - - assertTokenRemoved(authorized, token); - } - - private void assertTokenRemoved(boolean authorized, User token) { - assert authorized; - assert token != null; - } -} \ No newline at end of file diff --git a/src/test/java/com/netgrif/application/engine/authentication/service/IdentityServiceTest.java b/src/test/java/com/netgrif/application/engine/authentication/service/IdentityServiceTest.java new file mode 100644 index 00000000000..2b79d9487cd --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/authentication/service/IdentityServiceTest.java @@ -0,0 +1,501 @@ +package com.netgrif.application.engine.authentication.service; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.IdentityState; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authentication.domain.constants.AnonymIdentityConstants; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authorization.domain.constants.UserConstants; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.DateTimeField; +import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.startup.SuperCreator; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import com.netgrif.application.engine.workflow.service.throwable.CaseAlreadyExistsException; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class IdentityServiceTest { + + @Autowired + private TestHelper testHelper; + + @Autowired + private IdentityService identityService; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private IDataService dataService; + + @Autowired + private IPetriNetService petriNetService; + + @Autowired + private CaseRepository caseRepository; + + @Autowired + private SuperCreator superCreator; + + @BeforeEach + public void before() { + testHelper.truncateDbs(); + } + + @Test + void testFindById() throws InterruptedException { + Identity identity = createIdentity("username"); + Thread.sleep(2000); + assert identityService.findById(identity.getStringId()).isPresent(); + assert identityService.findById(new ObjectId().toString()).isEmpty(); + } + + @Test + void testFindByUsername() throws InterruptedException { + Identity identity = createIdentity("username"); + Thread.sleep(2000); + assert identityService.findByUsername(identity.getUsername()).isPresent(); + assert identityService.findByUsername("wrongUsername").isEmpty(); + } + + @Test + void testFindByLoggedIdentity() { + assert identityService.findByLoggedIdentity(null).isEmpty(); + assert identityService.findByLoggedIdentity(LoggedIdentity.with() + .username("username2") + .password("password") + .identityId(new ObjectId().toString()) + .build()).isEmpty(); + + Identity identity = createIdentity("username"); + LoggedIdentity loggedIdentity = identity.toSession(); + + Optional foundIdentityOpt = identityService.findByLoggedIdentity(loggedIdentity); + assert foundIdentityOpt.isPresent(); + assert foundIdentityOpt.get().getStringId().equals(identity.getStringId()); + } + + @Test + void testExistsByUsername() throws InterruptedException { + Identity identity = createIdentity("username"); + Thread.sleep(2000); + assert identityService.existsByUsername(identity.getUsername()); + assert !identityService.existsByUsername("wrongUsername"); + } + + @Test + void testFindActorIds() throws InterruptedException { + Identity identity = createIdentity("username", List.of(new ObjectId().toString(), new ObjectId().toString())); + Thread.sleep(2000); + Set actorIds = identityService.findActorIds(identity.getStringId()); + assert actorIds.size() == 3; + assert actorIds.contains(identity.getMainActorId()); + assert actorIds.contains(identity.getAdditionalActorIds().get(0)); + assert actorIds.contains(identity.getAdditionalActorIds().get(1)); + } + + @Test + void testFindAllByStateAndExpirationDateBefore() throws InterruptedException { + Process identityProcess = petriNetService.getNewestVersionByIdentifier("identity"); + caseRepository.deleteAllByPetriNetObjectId(identityProcess.getId()); + + doCreateIdentity(IdentityParams.with() + .username(new TextField("username1")) + .state(new EnumerationMapField(IdentityState.INVITED.name())) + .expirationDateTime(new DateTimeField(LocalDateTime.now().minusDays(1))) + .build()); + Identity identity = doCreateIdentity(IdentityParams.with() + .username(new TextField("username2")) + .state(new EnumerationMapField(IdentityState.BLOCKED.name())) + .expirationDateTime(new DateTimeField(LocalDateTime.now().minusDays(1))) + .build()); + doCreateIdentity(IdentityParams.with() + .username(new TextField("username3")) + .state(new EnumerationMapField(IdentityState.BLOCKED.name())) + .build()); + doCreateIdentity(IdentityParams.with() + .username(new TextField("username4")) + .state(new EnumerationMapField(IdentityState.BLOCKED.name())) + .expirationDateTime(new DateTimeField(LocalDateTime.now().plusDays(1))) + .build()); + + Thread.sleep(2000); + List identities = identityService.findAllByStateAndExpirationDateBefore(IdentityState.BLOCKED, + LocalDateTime.now()); + assert identities.size() == 1; + assert identities.get(0).getStringId().equals(identity.getStringId()); + + assert identityService.findAllByStateAndExpirationDateBefore(null, null).isEmpty(); + assert identityService.findAllByStateAndExpirationDateBefore(IdentityState.BLOCKED, null).isEmpty(); + assert identityService.findAllByStateAndExpirationDateBefore(null, LocalDateTime.now()).isEmpty(); + } + + @Test + void testFindAll() throws InterruptedException { + Process identityProcess = petriNetService.getNewestVersionByIdentifier("identity"); + caseRepository.deleteAllByPetriNetObjectId(identityProcess.getId()); + + assert identityService.findAll().isEmpty(); + + int identityCount = 101; // probably more than a page size + for (int i = 0; i < identityCount; ++i) { + createIdentity(String.format("username%d", i)); + } + + Thread.sleep(2000); + assert identityService.findAll().size() == identityCount; + } + + + @Test + void testCreate() throws InterruptedException { + assertThrows(IllegalArgumentException.class, () -> identityService.create(null)); + assertThrows(IllegalArgumentException.class, () -> identityService.create(IdentityParams.with() + .username(new TextField(AnonymIdentityConstants.defaultUsername())) + .build())); + assertThrows(IllegalArgumentException.class, () -> identityService.create(UserParams.with() + .email(new TextField("wrong type of parameters")) + .build())); + assertThrows(IllegalArgumentException.class, () -> identityService.create(IdentityParams.with().build())); + + String username = "username"; + String firstname = "firstname"; + String lastname = "lastname"; + String password = "password"; + LocalDateTime expirationDateTime = LocalDateTime.now(); + String registrationToken = "token"; + String mainActorId = new ObjectId().toString(); + String additionalActorId = new ObjectId().toString(); + String propertyKey = "property"; + String propertyValue = "isActive"; + + Identity identity = identityService.create(IdentityParams.with() + .username(new TextField(username)) + .firstname(new TextField(firstname)) + .lastname(new TextField(lastname)) + .password(new TextField(password)) + .expirationDateTime(new DateTimeField(expirationDateTime)) + .registrationToken(new TextField(registrationToken)) + .mainActor(CaseField.withValue(List.of(mainActorId))) + .additionalActors(CaseField.withValue(List.of(additionalActorId))) + .properties(Map.of(propertyKey, propertyValue)) + .build()); + + assert identity != null; + assert identity.getUsername().equals(username); + assert identity.getFirstname().equals(firstname); + assert identity.getLastname().equals(lastname); + assert identity.getPassword().equals(password); // not encoded + assert identity.getFullName().equals(String.join(" ", firstname, lastname)); + assert identity.getExpirationDate().toLocalDate().equals(expirationDateTime.toLocalDate()); + assert identity.getRegistrationToken().equals(registrationToken); + assert identity.getMainActorId().equals(mainActorId); + assert identity.getAdditionalActorIds().size() == 1; + assert identity.getAdditionalActorIds().get(0).equals(additionalActorId); + assert identity.isActive(); + assert identity.getCase().getProperties() != null; + assert identity.getCase().getProperties().size() == 1; + assert identity.getCase().getProperties().containsKey(propertyKey); + assert identity.getCase().getProperties().get(propertyKey).equals(propertyValue); + + Thread.sleep(2000); + assertThrows(CaseAlreadyExistsException.class, () -> identityService.create(IdentityParams.with() + .username(new TextField(username)) + .build())); + } + + @Test + void testCreateWithDefaultUser() { + Identity identity = identityService.createWithDefaultUser(IdentityParams.with() + .username(new TextField("username")) + .password(new TextField("password")) + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .build()); + + assert ObjectId.isValid(identity.getMainActorId()); + assert workflowService.findOne(identity.getMainActorId()).getProcessIdentifier().equals(UserConstants.PROCESS_IDENTIFIER); + } + + @Test + void testEncodePasswordAndCreate() { + String password = "password"; + + Identity identity = identityService.encodePasswordAndCreate(IdentityParams.with() + .username(new TextField("username")) + .password(new TextField(password)) + .build()); + + assert identity.getPassword() != null; + assert !identity.getPassword().equals(password); + } + + @Test + void testUpdate() { + assertThrows(IllegalArgumentException.class, () -> identityService.update(null, IdentityParams.with() + .username(new TextField("username")) + .build())); + + String username = "username"; + final Identity identity = doCreateIdentity(IdentityParams.with() + .username(new TextField("username")) + .build()); + + assert identity.getUsername().equals(username); + assert identity.getFirstname() == null; + assert identity.getLastname() == null; + assert identity.getCase().getProperties() == null || identity.getCase().getProperties().isEmpty(); + + assertThrows(IllegalArgumentException.class, () -> identityService.update(identity, null)); + assertThrows(IllegalArgumentException.class, () -> identityService.update(identity, IdentityParams.with() + .username(new TextField(null)) + .build())); + + String firstname = "firstname"; + String lastname = "lastname"; + String propertyKey = "property"; + String propertyValue = "isActive"; + Identity updatedIdentity = identityService.update(identity, IdentityParams.with() + .username(new TextField("username")) + .firstname(new TextField(firstname)) + .lastname(new TextField(lastname)) + .properties(Map.of(propertyKey, propertyValue)) + .build()); + + assert updatedIdentity.getStringId().equals(identity.getStringId()); + assert updatedIdentity.getUsername().equals(username); + assert updatedIdentity.getFirstname().equals(firstname); + assert updatedIdentity.getLastname().equals(lastname); + assert updatedIdentity.getCase().getProperties() != null; + assert updatedIdentity.getCase().getProperties().size() == 1; + assert updatedIdentity.getCase().getProperties().containsKey(propertyKey); + assert updatedIdentity.getCase().getProperties().get(propertyKey).equals(propertyValue); + } + + @Test + void testEncodePasswordAndUpdate() { + assertThrows(IllegalArgumentException.class, () -> identityService.encodePasswordAndUpdate(null, IdentityParams.with() + .username(new TextField("username")) + .password(new TextField("password")) + .build())); + + final Identity identity = doCreateIdentity(IdentityParams.with() + .username(new TextField("username")) + .build()); + + String password = "password"; + Identity updatedIdentity = identityService.encodePasswordAndUpdate(identity, IdentityParams.with() + .username(new TextField("username")) + .password(new TextField(password)) + .build()); + + assert updatedIdentity.getPassword() != null; + assert !updatedIdentity.getPassword().equals(password); + } + + @Test + void testAddAdditionalActor() { + String actorId = new ObjectId().toString(); + assertThrows(IllegalArgumentException.class , () -> identityService.addAdditionalActor(null, actorId)); + + final Identity identity = createIdentity("username"); + + assertThrows(IllegalArgumentException.class , () -> identityService.addAdditionalActor(identity, null)); + + Identity updatedIdentity = identityService.addAdditionalActor(identity, actorId); + assert updatedIdentity.getAdditionalActorIds().size() == 1; + assert updatedIdentity.getAdditionalActorIds().get(0).equals(actorId); + + String actorId2 = new ObjectId().toString(); + updatedIdentity = identityService.addAdditionalActor(updatedIdentity, actorId2); + assert updatedIdentity.getAdditionalActorIds().size() == 2; + assert updatedIdentity.getAdditionalActorIds().contains(actorId2); + } + + @Test + void testAddAdditionalActors() { + String actorId1 = new ObjectId().toString(); + String actorId2 = new ObjectId().toString(); + assertThrows(IllegalArgumentException.class , () -> identityService.addAdditionalActors(null, + Set.of(actorId1, actorId2))); + + final Identity identity = createIdentity("username"); + + assertThrows(IllegalArgumentException.class , () -> identityService.addAdditionalActors(identity, null)); + assertThrows(IllegalArgumentException.class , () -> identityService.addAdditionalActors(identity, null)); + + Identity updatedIdentity = identityService.addAdditionalActors(identity, Set.of(actorId1, actorId2)); + assert updatedIdentity.getAdditionalActorIds().size() == 2; + assert updatedIdentity.getAdditionalActorIds().contains(actorId1); + assert updatedIdentity.getAdditionalActorIds().contains(actorId2); + + String actorId3 = new ObjectId().toString(); + String actorId4 = new ObjectId().toString(); + updatedIdentity = identityService.addAdditionalActors(updatedIdentity, Set.of(actorId3, actorId4)); + assert updatedIdentity.getAdditionalActorIds().size() == 4; + assert updatedIdentity.getAdditionalActorIds().contains(actorId3); + assert updatedIdentity.getAdditionalActorIds().contains(actorId4); + } + + @Test + void testRemoveAllByStateAndExpirationDateBefore() throws InterruptedException { + Process identityProcess = petriNetService.getNewestVersionByIdentifier("identity"); + caseRepository.deleteAllByPetriNetObjectId(identityProcess.getId()); + + doCreateIdentity(IdentityParams.with() + .username(new TextField("username1")) + .state(new EnumerationMapField(IdentityState.INVITED.name())) + .expirationDateTime(new DateTimeField(LocalDateTime.now().minusDays(1))) + .build()); + Identity identity = doCreateIdentity(IdentityParams.with() + .username(new TextField("username2")) + .state(new EnumerationMapField(IdentityState.BLOCKED.name())) + .expirationDateTime(new DateTimeField(LocalDateTime.now().minusDays(1))) + .build()); + doCreateIdentity(IdentityParams.with() + .username(new TextField("username3")) + .state(new EnumerationMapField(IdentityState.BLOCKED.name())) + .build()); + doCreateIdentity(IdentityParams.with() + .username(new TextField("username4")) + .state(new EnumerationMapField(IdentityState.BLOCKED.name())) + .expirationDateTime(new DateTimeField(LocalDateTime.now().plusDays(1))) + .build()); + + Thread.sleep(2000); + + long countBefore = caseRepository.count(); + + assertThrows(IllegalArgumentException.class, () -> identityService.removeAllByStateAndExpirationDateBefore(null, null)); + assertThrows(IllegalArgumentException.class, () -> identityService.removeAllByStateAndExpirationDateBefore(IdentityState.BLOCKED, null)); + assertThrows(IllegalArgumentException.class, () -> identityService.removeAllByStateAndExpirationDateBefore(null, LocalDateTime.now())); + + assert caseRepository.count() == countBefore; + + TestHelper.login(superCreator.getSuperIdentity()); + List removedIdentities = identityService.removeAllByStateAndExpirationDateBefore(IdentityState.BLOCKED, + LocalDateTime.now()); + + assert removedIdentities.size() == 1; + assert removedIdentities.get(0).getStringId().equals(identity.getStringId()); + assertThrows(IllegalArgumentException.class, () -> workflowService.findOne(identity.getStringId())); + } + + @Test + void testForbiddenKeywords() { + assert !identityService.registerForbiddenKeywords(null); + assert !identityService.registerForbiddenKeywords(Set.of()); + + assert !identityService.removeForbiddenKeywords(null); + assert !identityService.removeForbiddenKeywords(Set.of()); + + Set keywords = Set.of("keyword1", "keyword2", "keyword3"); + assert !identityService.removeForbiddenKeywords(keywords); + assert identityService.registerForbiddenKeywords(keywords); + + assertThrows(IllegalArgumentException.class, () -> identityService.create(IdentityParams.with() + .username(new TextField("keyword1")) + .build())); + + assertThrows(IllegalArgumentException.class, () -> identityService.create(IdentityParams.with() + .username(new TextField("keyword2")) + .build())); + + assertThrows(IllegalArgumentException.class, () -> identityService.create(IdentityParams.with() + .username(new TextField("keyword3")) + .build())); + + assert identityService.removeForbiddenKeywords(Set.of("keyword1", "keyword2")); + + Identity identity = identityService.create(IdentityParams.with().username(new TextField("keyword1")).build()); + assert identity != null; + + identity = identityService.create(IdentityParams.with().username(new TextField("keyword2")).build()); + assert identity != null; + + assertThrows(IllegalArgumentException.class, () -> identityService.create(IdentityParams.with() + .username(new TextField("keyword3")) + .build())); + + identityService.clearForbiddenKeywords(); + + identity = identityService.create(IdentityParams.with().username(new TextField("keyword3")).build()); + assert identity != null; + } + + @Test + void testRemoveForbiddenKeywords() { + assert !identityService.removeForbiddenKeywords(null); + assert !identityService.removeForbiddenKeywords(Set.of()); + + Set keywords = Set.of("keyword1", "keyword2"); + assert identityService.registerForbiddenKeywords(keywords); + + assertThrows(IllegalArgumentException.class, () -> identityService.create(IdentityParams.with() + .username(new TextField("keyword1")) + .build())); + + assertThrows(IllegalArgumentException.class, () -> identityService.create(IdentityParams.with() + .username(new TextField("keyword2")) + .build())); + } + + private Identity createIdentity(String username) { + return doCreateIdentity(IdentityParams.with() + .username(new TextField(username)) + .password(new TextField("password")) + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .mainActor(CaseField.withValue(List.of(new ObjectId().toString()))) + .build()); + } + + private Identity createIdentity(String username, List additionalActorIds) { + return doCreateIdentity(IdentityParams.with() + .username(new TextField(username)) + .password(new TextField("password")) + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .mainActor(CaseField.withValue(List.of(new ObjectId().toString()))) + .additionalActors(CaseField.withValue(additionalActorIds)) + .build()); + } + + private Identity doCreateIdentity(IdentityParams params) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier("identity") + .title(params.getUsername().getRawValue()) + .build(); + Case identityCase = workflowService.createCase(createCaseParams).getCase(); + return new Identity(dataService.setData(new SetDataParams(identityCase, params.toDataSet(), null)).getCase()); + } + +} diff --git a/src/test/java/com/netgrif/application/engine/auth/service/RegistrationServiceTest.java b/src/test/java/com/netgrif/application/engine/authentication/service/RegistrationServiceTest.java similarity index 56% rename from src/test/java/com/netgrif/application/engine/auth/service/RegistrationServiceTest.java rename to src/test/java/com/netgrif/application/engine/authentication/service/RegistrationServiceTest.java index 890bbc98d43..61f6b7499f4 100644 --- a/src/test/java/com/netgrif/application/engine/auth/service/RegistrationServiceTest.java +++ b/src/test/java/com/netgrif/application/engine/authentication/service/RegistrationServiceTest.java @@ -1,14 +1,11 @@ -package com.netgrif.application.engine.auth.service; +package com.netgrif.application.engine.authentication.service; import com.netgrif.application.engine.TestHelper; -import com.netgrif.application.engine.auth.domain.RegisteredUser; -import com.netgrif.application.engine.auth.domain.User; -import com.netgrif.application.engine.auth.domain.repositories.UserRepository; -import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; -import com.netgrif.application.engine.auth.web.requestbodies.NewUserRequest; -import com.netgrif.application.engine.auth.web.requestbodies.RegistrationRequest; -import org.junit.jupiter.api.AfterEach; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.service.interfaces.IRegistrationService; +import com.netgrif.application.engine.authentication.web.requestbodies.NewIdentityRequest; +import com.netgrif.application.engine.authentication.web.requestbodies.RegistrationRequest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -27,10 +24,7 @@ public class RegistrationServiceTest { @Autowired - IRegistrationService service; - - @Autowired - UserRepository repository; + private IRegistrationService service; @Autowired private TestHelper testHelper; @@ -40,33 +34,29 @@ void before() { testHelper.truncateDbs(); } - - @AfterEach - public void cleanUp() { - repository.deleteAll(); - } - @Test // @WithMockUser(username = "myUser", roles = { "myAuthority" }) - public void testRegisterUser() throws InvalidUserTokenException { - NewUserRequest request = new NewUserRequest(); + public void testRegisterIdentity() throws InvalidIdentityTokenException { + NewIdentityRequest request = new NewIdentityRequest(); request.email = "test@test.com"; - RegisteredUser user = service.createNewUser(request); + Identity identity = service.createNewIdentity(request); RegistrationRequest registrationRequest = new RegistrationRequest(); - registrationRequest.token = service.encodeToken(user.getEmail(), user.getToken()); + registrationRequest.token = service.encodeToken(identity.getUsername(), identity.getRegistrationToken()); registrationRequest.password = "password"; - registrationRequest.name = "User"; - registrationRequest.surname = "Test"; + registrationRequest.firstname = "Identity"; + registrationRequest.lastname = "Test"; Authentication auth = Mockito.mock(Authentication.class); SecurityContext securityContext = Mockito.mock(SecurityContext.class); Mockito.when(securityContext.getAuthentication()).thenReturn(auth); SecurityContextHolder.setContext(securityContext); - User registered = (User) service.registerUser(registrationRequest); + Identity registered = service.registerIdentity(registrationRequest); assert registered != null; } + // todo: release/8.0.0 implement more tests + } diff --git a/src/test/java/com/netgrif/application/engine/authentication/service/TokenServiceTest.java b/src/test/java/com/netgrif/application/engine/authentication/service/TokenServiceTest.java new file mode 100644 index 00000000000..fdd443bf992 --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/authentication/service/TokenServiceTest.java @@ -0,0 +1,92 @@ +package com.netgrif.application.engine.authentication.service; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.IdentityState; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authentication.service.interfaces.IRegistrationService; +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.petrinet.domain.dataset.DateTimeField; +import com.netgrif.application.engine.petrinet.domain.dataset.EnumerationMapField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.startup.ImportHelper; +import com.netgrif.application.engine.startup.SuperCreator; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.io.ByteArrayOutputStream; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Optional; + +@ExtendWith(SpringExtension.class) +@ActiveProfiles({"test"}) +@SpringBootTest +public class TokenServiceTest { + + // todo: release/8.0.0 should be implemented in RegistrationServiceTest? + + @Autowired + private IRegistrationService service; + + @Autowired + private TestHelper testHelper; + + @Autowired + private IIdentityService identityService; + + @Autowired + private ImportHelper importHelper; + + @Autowired + private SuperCreator superCreator; + + @BeforeEach + public void setUp() { + testHelper.truncateDbs(); + } + + @Test + public void removeExpired() throws InterruptedException { + TestHelper.login(superCreator.getSuperIdentity()); + + Identity identity1 = importHelper.createIdentity(IdentityParams.with() + .username(new TextField("test@test.com")) + .registrationToken(new TextField("token")) + .expirationDateTime(new DateTimeField(LocalDateTime.now().minusDays(10))) + .state(new EnumerationMapField(IdentityState.INVITED.name())) + .build(), new ArrayList<>()); + + Identity identity2 = importHelper.createIdentity(IdentityParams.with() + .username(new TextField("test2@test.com")) + .registrationToken(new TextField("token2")) + .state(new EnumerationMapField(IdentityState.INVITED.name())) + .build(), new ArrayList<>()); + Thread.sleep(2000); + + service.removeExpiredIdentities(); + + assert identityService.findById(identity1.getStringId()).isEmpty(); + assert identityService.findById(identity2.getStringId()).isPresent(); + } + + @Test + public void authorizeToken() throws InterruptedException { + Identity identity = importHelper.createIdentity(IdentityParams.with() + .username(new TextField("test3@test.com")) + .registrationToken(new TextField("token3")) + .expirationDateTime(new DateTimeField(LocalDateTime.now().plusMinutes(10))) + .state(new EnumerationMapField(IdentityState.INVITED.name())) + .build(), new ArrayList<>()); + Thread.sleep(2000); + + assert service.verifyToken(service.encodeToken(identity.getUsername(), identity.getRegistrationToken()));; + } +} \ No newline at end of file diff --git a/src/test/java/com/netgrif/application/engine/authorization/domain/GroupTest.java b/src/test/java/com/netgrif/application/engine/authorization/domain/GroupTest.java new file mode 100644 index 00000000000..af6abae325a --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/authorization/domain/GroupTest.java @@ -0,0 +1,102 @@ +package com.netgrif.application.engine.authorization.domain; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.authorization.domain.constants.UserConstants; +import com.netgrif.application.engine.authorization.domain.params.GroupParams; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.startup.DefaultGroupRunner; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.DeleteCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class GroupTest { + @Autowired + private TestHelper testHelper; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private IDataService dataService; + + @Autowired + private DefaultGroupRunner defaultGroupRunner; + + @BeforeEach + void before() { + testHelper.truncateDbs(); + } + + @Test + public void testRemoveGroup() { + Group parentGroup = createGroup("parent test group", defaultGroupRunner.getDefaultGroup().getStringId()); + Group childGroup = createGroup("child test group", parentGroup.getStringId()); + User user = createUser("test@user.com", List.of(childGroup.getStringId())); + user = updateUserMembership(user, Set.of(parentGroup.getStringId())); + + assert childGroup.getParentGroupId() != null; + assert childGroup.getParentGroupId().equals(parentGroup.getStringId()); + assert user.getGroupIds().size() == 1; + + workflowService.deleteCase(new DeleteCaseParams(parentGroup.getCase())); + + user = new User(workflowService.findOne(user.getStringId())); + assert user.getGroupIds().isEmpty() || user.getGroupIds() == null; + + childGroup = new Group(workflowService.findOne(childGroup.getStringId())); + assert childGroup.getParentGroupId() == null; + } + + private User updateUserMembership(User user, Set groupIds) { + return new User(dataService.setData(new SetDataParams(user.getCase(), UserParams.with() + .groupIds(CaseField.withValue(new ArrayList<>(groupIds))) + .build() + .toDataSet(), null)).getCase()); + } + + private Group createGroup(String name, String parentGroupId) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(GroupConstants.PROCESS_IDENTIFIER) + .title(name) + .build(); + Case groupCase = workflowService.createCase(createCaseParams).getCase(); + return new Group(dataService.setData(new SetDataParams(groupCase, GroupParams.with() + .name(new TextField(name)) + .parentGroupId(CaseField.withValue(List.of(parentGroupId))) + .build() + .toDataSet(), null)).getCase()); + } + + private User createUser(String email, List additionalGroupIds) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(UserConstants.PROCESS_IDENTIFIER) + .title(email) + .build(); + Case userCase = workflowService.createCase(createCaseParams).getCase(); + return new User(dataService.setData(new SetDataParams(userCase, UserParams.with() + .email(new TextField(email)) + .groupIds(CaseField.withValue(additionalGroupIds)) + .build() + .toDataSet(), null)).getCase()); + } +} diff --git a/src/test/java/com/netgrif/application/engine/authorization/service/AllActorServiceTest.java b/src/test/java/com/netgrif/application/engine/authorization/service/AllActorServiceTest.java new file mode 100644 index 00000000000..cc66d9f677e --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/authorization/service/AllActorServiceTest.java @@ -0,0 +1,121 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.constants.IdentityConstants; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authorization.domain.Actor; +import com.netgrif.application.engine.authorization.domain.Group; +import com.netgrif.application.engine.authorization.domain.User; +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.authorization.domain.constants.UserConstants; +import com.netgrif.application.engine.authorization.domain.params.GroupParams; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.List; +import java.util.Optional; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class AllActorServiceTest { + + @Autowired + private TestHelper testHelper; + + @Autowired + private AllActorService allActorService; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private IDataService dataService; + + @Autowired + private CaseRepository caseRepository; + + @BeforeEach + void before() { + testHelper.truncateDbs(); + } + + @Test + public void testFindById() { + assert allActorService.findById(null).isEmpty(); + assert allActorService.findById(new ObjectId().toString()).isEmpty(); + + User user = createUser("s@meemail.com"); + + Optional foundActorOpt = allActorService.findById(user.getStringId()); + assert foundActorOpt.isPresent(); + } + + @Test + public void testFindAll() { + caseRepository.deleteAll(); + + assert allActorService.findAll().isEmpty(); + + Identity identity = createIdentity("not an actor"); + Actor actor1 = createUser("actor1@test.com"); + Actor actor2 = createGroup("actor 2"); + + List actors = allActorService.findAll(); + assert actors.size() == 2; + assert actors.stream().anyMatch(actor -> actor.getStringId().equals(actor1.getStringId())); + assert actors.stream().anyMatch(actor -> actor.getStringId().equals(actor2.getStringId())); + assert actors.stream().noneMatch(actor -> actor.getStringId().equals(identity.getStringId())); + } + + private Group createGroup(String name) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(GroupConstants.PROCESS_IDENTIFIER) + .title(name) + .build(); + Case groupCase = workflowService.createCase(createCaseParams).getCase(); + return new Group(dataService.setData(new SetDataParams(groupCase, GroupParams.with() + .name(new TextField(name)) + .build() + .toDataSet(), null)).getCase()); + } + + private User createUser(String email) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(UserConstants.PROCESS_IDENTIFIER) + .title(email) + .build(); + Case userCase = workflowService.createCase(createCaseParams).getCase(); + return new User(dataService.setData(new SetDataParams(userCase, UserParams.with() + .email(new TextField(email)) + .build() + .toDataSet(), null)).getCase()); + } + + private Identity createIdentity(String username) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(IdentityConstants.PROCESS_IDENTIFIER) + .title(username) + .build(); + Case identityCase = workflowService.createCase(createCaseParams).getCase(); + return new Identity(dataService.setData(new SetDataParams(identityCase, IdentityParams.with() + .username(new TextField(username)) + .build() + .toDataSet(), null)).getCase()); + } +} diff --git a/src/test/java/com/netgrif/application/engine/authorization/service/ApplicationAuthorizationServiceTest.java b/src/test/java/com/netgrif/application/engine/authorization/service/ApplicationAuthorizationServiceTest.java new file mode 100644 index 00000000000..3c2623ddf26 --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/authorization/service/ApplicationAuthorizationServiceTest.java @@ -0,0 +1,147 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.domain.ApplicationRoleAssignment; +import com.netgrif.application.engine.authorization.domain.Group; +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.authorization.domain.User; +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.authorization.domain.params.GroupParams; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.authorization.domain.repositories.RoleAssignmentRepository; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.ArrayList; +import java.util.Optional; +import java.util.Set; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class ApplicationAuthorizationServiceTest { + + @Autowired + private ApplicationAuthorizationService authorizationService; + + @Autowired + private TestHelper testHelper; + + @Autowired + private IIdentityService identityService; + + @Autowired + private RoleAssignmentRepository roleAssignmentRepository; + + @Autowired + private ApplicationRoleRunner applicationRoleRunner; + + @Autowired + private IUserService userService; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private IDataService dataService; + + private Identity testIdentity; + + private Group testGroup; + + @BeforeEach + public void beforeEach() { + testHelper.truncateDbs(); + + testIdentity = identityService.createWithDefaultUser(IdentityParams.with() + .username(new TextField("username")) + .password(new TextField("password")) + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .build()); + + TestHelper.login(testIdentity); + } + + @Test + public void hasApplicationRole() { + assert !authorizationService.hasApplicationRole(null); + assert !authorizationService.hasApplicationRole("nonExistingRoleName"); + assert !authorizationService.hasApplicationRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + + Role role = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + ApplicationRoleAssignment assignment = new ApplicationRoleAssignment(); + assignment.setActorId(testIdentity.getMainActorId()); + assignment.setRoleId(role.getStringId()); + roleAssignmentRepository.save(assignment); + + assert authorizationService.hasApplicationRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + + TestHelper.logout(); + assert !authorizationService.hasApplicationRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + } + + @Test + public void hasApplicationRoleByGroups() { + User testUser = initializeTestUserWithGroup(); + assert !roleAssignmentRepository.findAllByActorId(testUser.getStringId()).iterator().hasNext(); + + assert !authorizationService.hasApplicationRole(null); + assert !authorizationService.hasApplicationRole("nonExistingRoleName"); + assert !authorizationService.hasApplicationRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + + Role role = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + ApplicationRoleAssignment assignment = new ApplicationRoleAssignment(); + assignment.setActorId(testGroup.getStringId()); + assignment.setRoleId(role.getStringId()); + roleAssignmentRepository.save(assignment); + + assert authorizationService.hasApplicationRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + + TestHelper.logout(); + assert !authorizationService.hasApplicationRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + } + + private User updateUserMembership(User user, Set groupIds) { + return new User(dataService.setData(new SetDataParams(user.getCase(), UserParams.with() + .groupIds(CaseField.withValue(new ArrayList<>(groupIds))) + .build() + .toDataSet(), null)).getCase()); + } + + private User initializeTestUserWithGroup() { + Optional testUserOpt = userService.findById(testIdentity.getMainActorId()); + assert testUserOpt.isPresent(); + testGroup = createGroup("test group"); + return updateUserMembership(testUserOpt.get(), Set.of(testGroup.getStringId())); + } + + private Group createGroup(String name) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(GroupConstants.PROCESS_IDENTIFIER) + .title(name) + .build(); + Case groupCase = workflowService.createCase(createCaseParams).getCase(); + return new Group(dataService.setData(new SetDataParams(groupCase, GroupParams.with() + .name(new TextField(name)) + .build() + .toDataSet(), null)).getCase()); + } +} diff --git a/src/test/java/com/netgrif/application/engine/authorization/service/CaseAuthorizationServiceTest.java b/src/test/java/com/netgrif/application/engine/authorization/service/CaseAuthorizationServiceTest.java new file mode 100644 index 00000000000..03b8876a29c --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/authorization/service/CaseAuthorizationServiceTest.java @@ -0,0 +1,380 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.domain.*; +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.authorization.domain.params.GroupParams; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.authorization.domain.repositories.CaseRoleRepository; +import com.netgrif.application.engine.authorization.domain.repositories.ProcessRoleRepository; +import com.netgrif.application.engine.authorization.domain.repositories.RoleAssignmentRepository; +import com.netgrif.application.engine.authorization.service.interfaces.IGroupService; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; +import com.netgrif.application.engine.petrinet.domain.VersionType; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; +import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; +import com.netgrif.application.engine.startup.ImportHelper; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import com.netgrif.application.engine.petrinet.domain.Process; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class CaseAuthorizationServiceTest { + + @Autowired + private CaseAuthorizationService authorizationService; + + @Autowired + private IIdentityService identityService; + + @Autowired + private IPetriNetService petriNetService; + + @Autowired + private RoleAssignmentRepository roleAssignmentRepository; + + @Autowired + private ProcessRoleRepository processRoleRepository; + + @Autowired + private CaseRoleRepository caseRoleRepository; + + @Autowired + private ApplicationRoleRunner applicationRoleRunner; + + @Autowired + private ImportHelper importHelper; + + @Autowired + private TestHelper testHelper; + + @Autowired + private IUserService userService; + + @Autowired + private IGroupService groupService; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private IDataService dataService; + + private Identity testIdentity; + + private Group testGroup; + + private Process testProcess; + + private Process testProcessWithDefault; + + @BeforeEach + public void beforeEach() throws IOException, MissingPetriNetMetaDataException { + testHelper.truncateDbs(); + + testIdentity = identityService.createWithDefaultUser(IdentityParams.with() + .username(new TextField("username")) + .password(new TextField("password")) + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .build()); + + testProcess = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/petriNets/case_authorization_test.xml"), + VersionType.MAJOR, userService.getSystemUser().getStringId())).getProcess(); + + testProcessWithDefault = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/petriNets/case_authorization_default_test.xml"), + VersionType.MAJOR, userService.getSystemUser().getStringId())).getProcess(); + + TestHelper.login(testIdentity); + } + + @Test + public void canCallCreate() { + assert !authorizationService.canCallCreate(null); + assert !authorizationService.canCallCreate("wrong id"); + + // order of assertions is important! + assert !authorizationService.canCallCreate(null); + assert authorizationService.canCallCreate(testProcessWithDefault.getStringId()); + assert !authorizationService.canCallCreate(testProcess.getStringId()); + + assignProcessRole(testIdentity.getMainActorId(), processRoleRepository.findByImportId("pos_process_role")); + assert authorizationService.canCallCreate(testProcess.getStringId()); + + assignProcessRole(testIdentity.getMainActorId(), processRoleRepository.findByImportId("neg_process_role")); + assert !authorizationService.canCallCreate(testProcess.getStringId()); + + assignAppRole(testIdentity.getMainActorId(), applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE)); + assert authorizationService.canCallCreate(testProcess.getStringId()); + + TestHelper.logout(); + assert !authorizationService.canCallCreate(testProcess.getStringId()); + } + + @Test + public void canCallCreateByGroups() { + // order of assertions is important! + User testUser = initializeTestUserWithGroup(); + + assert !roleAssignmentRepository.findAllByActorId(testUser.getStringId()).iterator().hasNext(); + + assert !authorizationService.canCallCreate(null); + assert !authorizationService.canCallCreate(testProcessWithDefault.getStringId()); + assert !authorizationService.canCallCreate(testProcess.getStringId()); + + testGroup = updateGroupWithParent(testGroup, groupService.getDefaultGroup().getStringId()); + assert authorizationService.canCallCreate(testProcessWithDefault.getStringId()); + assert !authorizationService.canCallCreate(testProcess.getStringId()); + + assignProcessRole(testGroup.getStringId(), processRoleRepository.findByImportId("pos_process_role")); + assert authorizationService.canCallCreate(testProcess.getStringId()); + + assignProcessRole(testGroup.getStringId(), processRoleRepository.findByImportId("neg_process_role")); + assert !authorizationService.canCallCreate(testProcess.getStringId()); + + assignAppRole(testGroup.getStringId(), applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE)); + assert authorizationService.canCallCreate(testProcess.getStringId()); + + TestHelper.logout(); + assert !authorizationService.canCallCreate(testProcess.getStringId()); + } + + @Test + public void canCallDelete() { + assert !authorizationService.canCallDelete(null); + assert !authorizationService.canCallDelete("wrong id"); + + // order of assertions is important! + Case testCase = importHelper.createCase("test", testProcess); + Case testCaseWithDefault = importHelper.createCase("test with default role", testProcessWithDefault); + + assert !authorizationService.canCallDelete(testCase.getStringId()); + assert authorizationService.canCallDelete(testCaseWithDefault.getStringId()); + + assignProcessRole(testIdentity.getMainActorId(), processRoleRepository.findByImportId("pos_process_role")); + assert authorizationService.canCallDelete(testCase.getStringId()); + + assignProcessRole(testIdentity.getMainActorId(), processRoleRepository.findByImportId("neg_process_role")); + assert !authorizationService.canCallDelete(testCase.getStringId()); + + assignCaseRole(testIdentity.getMainActorId(), caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), + "pos_case_role"), testCase); + assert authorizationService.canCallDelete(testCase.getStringId()); + + assignCaseRole(testIdentity.getMainActorId(), caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), + "neg_case_role"), testCase); + assert !authorizationService.canCallDelete(testCase.getStringId()); + + assignAppRole(testIdentity.getMainActorId(), applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE)); + assert authorizationService.canCallDelete(testCase.getStringId()); + + TestHelper.logout(); + assert !authorizationService.canCallDelete(testCase.getStringId()); + } + + @Test + public void canCallDeleteByGroups() { + // order of assertions is important! + Case testCase = importHelper.createCase("test", testProcess); + Case testCaseWithDefault = importHelper.createCase("test with default role", testProcessWithDefault); + + User testUser = initializeTestUserWithGroup(); + + assert !roleAssignmentRepository.findAllByActorId(testUser.getStringId()).iterator().hasNext(); + + assert !authorizationService.canCallDelete(testCase.getStringId()); + assert !authorizationService.canCallDelete(testCaseWithDefault.getStringId()); + + testGroup = updateGroupWithParent(testGroup, groupService.getDefaultGroup().getStringId()); + assert !authorizationService.canCallDelete(testCase.getStringId()); + assert authorizationService.canCallDelete(testCaseWithDefault.getStringId()); + + assignProcessRole(testGroup.getStringId(), processRoleRepository.findByImportId("pos_process_role")); + assert authorizationService.canCallDelete(testCase.getStringId()); + + assignProcessRole(testGroup.getStringId(), processRoleRepository.findByImportId("neg_process_role")); + assert !authorizationService.canCallDelete(testCase.getStringId()); + + assignCaseRole(testGroup.getStringId(), caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), + "pos_case_role"), testCase); + assert authorizationService.canCallDelete(testCase.getStringId()); + + assignCaseRole(testGroup.getStringId(), caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), + "neg_case_role"), testCase); + assert !authorizationService.canCallDelete(testCase.getStringId()); + + assignAppRole(testGroup.getStringId(), applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE)); + assert authorizationService.canCallDelete(testCase.getStringId()); + + TestHelper.logout(); + assert !authorizationService.canCallDelete(testCase.getStringId()); + } + + @Test + public void canCallView() { + // order of assertions is important! + assert !authorizationService.canView(null); + assert !authorizationService.canView("wrong id"); + + Case testCase = importHelper.createCase("test", testProcess); + Case testCaseWithDefault = importHelper.createCase("test with default role", testProcessWithDefault); + + assert !authorizationService.canView(testCase.getStringId()); + assert authorizationService.canView(testCaseWithDefault.getStringId()); + + assignProcessRole(testIdentity.getMainActorId(), processRoleRepository.findByImportId("pos_process_role")); + assert authorizationService.canView(testCase.getStringId()); + + assignProcessRole(testIdentity.getMainActorId(), processRoleRepository.findByImportId("neg_process_role")); + assert !authorizationService.canView(testCase.getStringId()); + + assignCaseRole(testIdentity.getMainActorId(), caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), + "pos_case_role"), testCase); + assert authorizationService.canView(testCase.getStringId()); + + assignCaseRole(testIdentity.getMainActorId(), caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), + "neg_case_role"), testCase); + assert !authorizationService.canView(testCase.getStringId()); + + assignAppRole(testIdentity.getMainActorId(), applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE)); + assert authorizationService.canView(testCase.getStringId()); + + TestHelper.logout(); + assert !authorizationService.canView(testCase.getStringId()); + } + + @Test + public void canCallViewByGroups() { + // order of assertions is important! + Case testCase = importHelper.createCase("test", testProcess); + Case testCaseWithDefault = importHelper.createCase("test with default role", testProcessWithDefault); + + User testUser = initializeTestUserWithGroup(); + + assert !authorizationService.canView(testCase.getStringId()); + assert !authorizationService.canView(testCaseWithDefault.getStringId()); + + testGroup = updateGroupWithParent(testGroup, groupService.getDefaultGroup().getStringId()); + assert !authorizationService.canView(testCase.getStringId()); + assert authorizationService.canView(testCaseWithDefault.getStringId()); + + assignProcessRole(testGroup.getStringId(), processRoleRepository.findByImportId("pos_process_role")); + assert authorizationService.canView(testCase.getStringId()); + + assignProcessRole(testGroup.getStringId(), processRoleRepository.findByImportId("neg_process_role")); + assert !authorizationService.canView(testCase.getStringId()); + + assignCaseRole(testGroup.getStringId(), caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), + "pos_case_role"), testCase); + assert authorizationService.canView(testCase.getStringId()); + + assignCaseRole(testGroup.getStringId(), caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), + "neg_case_role"), testCase); + assert !authorizationService.canView(testCase.getStringId()); + + assignAppRole(testGroup.getStringId(), applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE)); + assert authorizationService.canView(testCase.getStringId()); + + TestHelper.logout(); + assert !authorizationService.canView(testCase.getStringId()); + } + + @Test + void testGroupPermissionLoopBreakdown() { + Group testGroup = createGroup("test group"); + // forbidden reference loop: testGroup -> defaultGroup -> testGroup -> ... + updateGroupWithParent(groupService.getDefaultGroup(), testGroup.getStringId()); + updateGroupWithParent(testGroup, groupService.getDefaultGroup().getStringId()); + + Optional testUserOpt = userService.findById(testIdentity.getMainActorId()); + assert testUserOpt.isPresent(); + // to make it harder, user is a member of both groups + updateUserMembership(testUserOpt.get(), Set.of(testGroup.getStringId(), groupService.getDefaultGroup().getStringId())); + + assert authorizationService.canCallCreate(testProcessWithDefault.getStringId()); + + Case testCaseWithDefault = importHelper.createCase("test with default role", testProcessWithDefault); + assert authorizationService.canCallDelete(testCaseWithDefault.getStringId()); + } + + private void assignProcessRole(String actorId, ProcessRole role) { + RoleAssignment assignment = new ProcessRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(role.getStringId()); + roleAssignmentRepository.save(assignment); + } + + private void assignCaseRole(String actorId, CaseRole role, Case testCase) { + CaseRoleAssignment assignment = new CaseRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(role.getStringId()); + assignment.setCaseId(testCase.getStringId()); + roleAssignmentRepository.save(assignment); + } + + private void assignAppRole(String actorId, ApplicationRole role) { + ApplicationRoleAssignment assignment = new ApplicationRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(role.getStringId()); + roleAssignmentRepository.save(assignment); + } + + private Group updateGroupWithParent(Group group, String parentGroupId) { + return new Group(dataService.setData(new SetDataParams(group.getCase(), GroupParams.with() + .parentGroupId(CaseField.withValue(List.of(parentGroupId))) + .build() + .toDataSet(), null)).getCase()); + } + + private User updateUserMembership(User user, Set groupIds) { + return new User(dataService.setData(new SetDataParams(user.getCase(), UserParams.with() + .groupIds(CaseField.withValue(new ArrayList<>(groupIds))) + .build() + .toDataSet(), null)).getCase()); + } + + private User initializeTestUserWithGroup() { + Optional testUserOpt = userService.findById(testIdentity.getMainActorId()); + assert testUserOpt.isPresent(); + testGroup = createGroup("test group"); + return updateUserMembership(testUserOpt.get(), Set.of(testGroup.getStringId())); + } + + private Group createGroup(String name) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(GroupConstants.PROCESS_IDENTIFIER) + .title(name) + .build(); + Case groupCase = workflowService.createCase(createCaseParams).getCase(); + return new Group(dataService.setData(new SetDataParams(groupCase, GroupParams.with() + .name(new TextField(name)) + .build() + .toDataSet(), null)).getCase()); + } +} diff --git a/src/test/java/com/netgrif/application/engine/authorization/service/GroupServiceTest.java b/src/test/java/com/netgrif/application/engine/authorization/service/GroupServiceTest.java new file mode 100644 index 00000000000..6e974761829 --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/authorization/service/GroupServiceTest.java @@ -0,0 +1,415 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authorization.domain.Group; +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.authorization.domain.params.GroupParams; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.startup.DefaultGroupRunner; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository; +import com.netgrif.application.engine.workflow.service.SystemCaseFactoryRegistry; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import com.netgrif.application.engine.workflow.service.throwable.CaseAlreadyExistsException; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class GroupServiceTest { + + @Autowired + private TestHelper testHelper; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private CaseRepository caseRepository; + + @Autowired + private IPetriNetService petriNetService; + + @Autowired + private IDataService dataService; + + @Autowired + private GroupService groupService; + + @Autowired + private DefaultGroupRunner defaultGroupRunner; + + @Autowired + private SystemCaseFactoryRegistry systemCaseFactoryRegistry; + + @BeforeEach + void before() { + testHelper.truncateDbs(); + } + + @Test + void testFindByName() throws InterruptedException { + assert groupService.findByName(null).isEmpty(); + assert groupService.findByName("non existing name").isEmpty(); + + String name = "group name"; + createGroup(name); + + Thread.sleep(2000); + assert groupService.findByName(name).isPresent(); + } + + @Test + void testExistsByName() throws InterruptedException { + assert !groupService.existsByName(null); + assert !groupService.existsByName("non existing name"); + + String name = "group name"; + createGroup(name); + + Thread.sleep(2000); + assert groupService.existsByName(name); + } + + @Test + void testFindById() { + assert groupService.findById(null).isEmpty(); + assert groupService.findById(new ObjectId().toString()).isEmpty(); + + String name = "group name"; + Group group = createGroup(name); + + assert groupService.findById(group.getStringId()).isPresent(); + } + + @Test + void testExistsById() { + assert !groupService.existsById(null); + assert !groupService.existsById(new ObjectId().toString()); + + String name = "group name"; + Group group = createGroup(name); + + assert groupService.existsById(group.getStringId()); + } + + @Test + void testFindAll() throws InterruptedException { + Process groupProcess = petriNetService.getNewestVersionByIdentifier(GroupConstants.PROCESS_IDENTIFIER); + caseRepository.deleteAllByPetriNetObjectId(groupProcess.getId()); + + assert groupService.findAll().isEmpty(); + + createGroup("group name"); + createGroup("group name 2"); + + Thread.sleep(2000); + assert groupService.findAll().size() == 2; + } + + @Test + void testCreate() throws InterruptedException { + String name = "group name"; + String propertyKey = "property"; + String propertyValue = "isActive"; + Group parentGroup = createGroup("parent group"); + Group group = groupService.create(GroupParams.with() + .name(new TextField(name)) + .groupIds(CaseField.withValue(List.of(defaultGroupRunner.getDefaultGroup().getStringId()))) + .parentGroupId(CaseField.withValue(List.of(parentGroup.getStringId()))) + .properties(Map.of(propertyKey, propertyValue)) + .build()); + + assert group != null && group.getCase() != null; + assert group.getName().equals(name); + assert group.getParentGroupId() != null; + assert group.getParentGroupId().equals(parentGroup.getStringId()); + assert group.getGroupIds() != null; + assert group.getGroupIds().size() == 1; + assert group.getGroupIds().contains(defaultGroupRunner.getDefaultGroup().getStringId()); + assert group.getCase().getProperties() != null; + assert group.getCase().getProperties().size() == 1; + assert group.getCase().getProperties().containsKey(propertyKey); + assert group.getCase().getProperties().get(propertyKey).equals(propertyValue); + + assertThrows(IllegalArgumentException.class, () -> groupService.create(null)); + assertThrows(IllegalArgumentException.class, () -> groupService.create(GroupParams.with().build())); + assertThrows(IllegalArgumentException.class, () -> groupService.create(GroupParams.with() + .name(new TextField(GroupConstants.DEFAULT_GROUP_NAME)) + .build())); + assertThrows(IllegalArgumentException.class, () -> groupService.create(UserParams.with() + .email(new TextField("wrong type of params")) + .build())); + // todo: release/8.0.0 allowed nets validation is not working +// assertThrows(IllegalArgumentException.class, () -> groupService.create(GroupParams.with() +// .name(new TextField(name)) +// .memberIds(CaseField.withValue(List.of(superCreator.getSuperIdentity().getStringId()))) // wrong process identifier +// .parentGroupId(CaseField.withValue(List.of(parentGroup.getStringId()))) +// .build())); + + Thread.sleep(2000); + assertThrows(CaseAlreadyExistsException.class, () -> groupService.create(GroupParams.with() + .name(new TextField(name)) + .build())); + } + @Test + void testCreateDefaultParent() { + String name = "group name"; + Group group = groupService.create(GroupParams.with() + .name(new TextField(name)) + .build()); + + assert group.getParentGroupId() != null; + assert group.getParentGroupId().equals(defaultGroupRunner.getDefaultGroup().getStringId()); + } + + @Test + void testUpdate() { + String name = "group name"; + + Group parentGroup = createGroup("parent group name"); + Group group = createGroup(name); + assert group.getName().equals(name); + assert group.getGroupIds() == null || group.getGroupIds().isEmpty(); + assert group.getParentGroupId() != null; + assert group.getParentGroupId().equals(defaultGroupRunner.getDefaultGroup().getStringId()); + assert group.getCase().getProperties() == null || group.getCase().getProperties().isEmpty(); + + assertThrows(IllegalArgumentException.class, () -> groupService.update(group, null)); + assertThrows(IllegalArgumentException.class, () -> groupService.update(null, GroupParams.with() + .name(new TextField("some name")) + .parentGroupId(CaseField.withValue(List.of(parentGroup.getStringId()))) + .parentGroupId(CaseField.withValue(List.of(parentGroup.getStringId()))) + .build())); + + // todo: release/8.0.0 allowed nets validation is not working +// assertThrows(IllegalArgumentException.class, () -> groupService.update(group, GroupParams.with() +// // wrong process identifier +// .memberIds(CaseField.withValue(List.of(superCreator.getSuperIdentity().getStringId()))) +// .build())); + + assertThrows(IllegalArgumentException.class, () -> groupService.update(group, GroupParams.with() + // self reference should be forbidden + .parentGroupId(CaseField.withValue(List.of(group.getStringId()))) + .build())); + assert ((Group) systemCaseFactoryRegistry.fromCase(workflowService.findOne(group.getStringId()))) + .getParentGroupId().equals(defaultGroupRunner.getDefaultGroup().getStringId()); + + assertThrows(IllegalArgumentException.class, () -> groupService.update(group, GroupParams.with() + // self reference should be forbidden + .groupIds(CaseField.withValue(List.of(group.getStringId()))) + .build())); + assert ((Group) systemCaseFactoryRegistry.fromCase(workflowService.findOne(group.getStringId()))) + .getGroupIds() == null || group.getGroupIds().isEmpty(); + + String newName = "new group name"; + String propertyKey = "property"; + String propertyValue = "isActive"; + Group updatedGroup = groupService.update(group, GroupParams.with() + .name(new TextField(newName)) + .groupIds(CaseField.withValue(List.of(defaultGroupRunner.getDefaultGroup().getStringId()))) + .parentGroupId(CaseField.withValue(List.of(parentGroup.getStringId()))) + .properties(Map.of(propertyKey, propertyValue)) + .build()); + + assert group.getStringId().equals(updatedGroup.getStringId()); + assert updatedGroup.getName().equals(newName); + assert updatedGroup.getGroupIds() != null; + assert updatedGroup.getGroupIds().size() == 1; + assert updatedGroup.getGroupIds().contains(defaultGroupRunner.getDefaultGroup().getStringId()); + assert updatedGroup.getParentGroupId() != null; + assert updatedGroup.getParentGroupId().equals(parentGroup.getStringId()); + assert updatedGroup.getCase().getProperties() != null; + assert updatedGroup.getCase().getProperties().size() == 1; + assert updatedGroup.getCase().getProperties().containsKey(propertyKey); + assert updatedGroup.getCase().getProperties().get(propertyKey).equals(propertyValue); + } + + @Test + void testGetDefaultGroup() { + Process process = petriNetService.getNewestVersionByIdentifier(GroupConstants.PROCESS_IDENTIFIER); + caseRepository.deleteAllByPetriNetObjectId(process.getObjectId()); + defaultGroupRunner.clearCache(); + + assert caseRepository.findAllByProcessIdentifier(GroupConstants.PROCESS_IDENTIFIER).isEmpty(); + + Group defaultGroup = groupService.getDefaultGroup(); + + assert defaultGroup != null; + assert defaultGroup.getName().equals(GroupConstants.DEFAULT_GROUP_NAME); + assert defaultGroup.getParentGroupId() == null; + assert caseRepository.findAllByProcessIdentifier(GroupConstants.PROCESS_IDENTIFIER).size() == 1; + Optional groupCaseOpt = caseRepository.findById(defaultGroup.getStringId()); + assert groupCaseOpt.isPresent(); + assert groupCaseOpt.get().getStringId().equals(defaultGroup.getStringId()); + } + + @Test + void testAddGroup() { + Group group = createGroup("test group"); + Group memberGroup = createGroup("member group"); + assert memberGroup.getGroupIds() == null || memberGroup.getGroupIds().isEmpty(); + + assertThrows(IllegalArgumentException.class, () -> groupService.addGroup(null, group.getStringId())); + final Group finalGroup = memberGroup; + assertThrows(IllegalArgumentException.class, () -> groupService.addGroup(finalGroup, null)); + assertThrows(IllegalArgumentException.class, () -> groupService.addGroup(finalGroup, finalGroup.getStringId())); + Group actualMemberGroup = (Group) systemCaseFactoryRegistry.fromCase(workflowService.findOne(finalGroup.getStringId())); + assert actualMemberGroup.getGroupIds() == null || actualMemberGroup.getGroupIds().isEmpty(); + + memberGroup = groupService.addGroup(memberGroup, group.getStringId()); + assert memberGroup.getGroupIds() != null; + assert memberGroup.getGroupIds().size() == 1; + assert memberGroup.getGroupIds().get(0).equals(group.getStringId()); + } + + @Test + void testAddGroups() { + Group group1 = createGroup("test group 1"); + Group group2 = createGroup("test group 2"); + Group memberGroup = createGroup("member group"); + assert memberGroup.getGroupIds() == null || memberGroup.getGroupIds().isEmpty(); + + assertThrows(IllegalArgumentException.class, () -> groupService.addGroups(null, Set.of(group1.getStringId(), + group2.getStringId()))); + final Group finalGroup = memberGroup; + assertThrows(IllegalArgumentException.class, () -> groupService.addGroups(finalGroup, null)); + assertThrows(IllegalArgumentException.class, () -> groupService.addGroups(finalGroup, Set.of(group1.getStringId(), + group2.getStringId(), finalGroup.getStringId()))); + Group actualMemberGroup = (Group) systemCaseFactoryRegistry.fromCase(workflowService.findOne(finalGroup.getStringId())); + assert actualMemberGroup.getGroupIds() == null || actualMemberGroup.getGroupIds().isEmpty(); + + Set groupIdsToAdd = new HashSet<>(List.of(group1.getStringId(), group2.getStringId(), + defaultGroupRunner.getDefaultGroup().getStringId())); + groupIdsToAdd.add(null); + + memberGroup = groupService.addGroups(memberGroup, groupIdsToAdd); + assert memberGroup.getGroupIds() != null; + assert memberGroup.getGroupIds().size() == 3; + assert memberGroup.getGroupIds().contains(defaultGroupRunner.getDefaultGroup().getStringId()); + assert memberGroup.getGroupIds().contains(group1.getStringId()); + assert memberGroup.getGroupIds().contains(group2.getStringId()); + } + + @Test + void testRemoveGroup() { + Group group = createGroup("test group"); + Group memberGroup = createGroup("member group", List.of(group.getStringId())); + assert memberGroup.getGroupIds() != null; + assert memberGroup.getGroupIds().size() == 1; + + assertThrows(IllegalArgumentException.class, () -> groupService.removeGroup(null, group.getStringId())); + final Group finalGroup = memberGroup; + assertThrows(IllegalArgumentException.class, () -> groupService.removeGroup(finalGroup, null)); + + memberGroup = groupService.removeGroup(memberGroup, defaultGroupRunner.getDefaultGroup().getStringId()); + assert memberGroup.getGroupIds() != null; + assert memberGroup.getGroupIds().size() == 1; + + memberGroup = groupService.removeGroup(memberGroup, group.getStringId()); + assert memberGroup.getGroupIds() == null || memberGroup.getGroupIds().isEmpty(); + + assert groupService.removeGroup(memberGroup, group.getStringId()) != null; + } + + @Test + void testRemoveGroups() { + Group group1 = createGroup("test group 1"); + Group group2 = createGroup("test group 2"); + Group memberGroup = createGroup("member group", List.of(group1.getStringId(), group2.getStringId())); + assert memberGroup.getGroupIds() != null; + assert memberGroup.getGroupIds().size() == 2; + + assertThrows(IllegalArgumentException.class, () -> groupService.removeGroups(null, Set.of(group1.getStringId()))); + final Group finalGroup = memberGroup; + assertThrows(IllegalArgumentException.class, () -> groupService.removeGroups(finalGroup, null)); + + Set groupIdsToRemove = new HashSet<>(Set.of(group1.getStringId(), group2.getStringId(), + defaultGroupRunner.getDefaultGroup().getStringId())); + groupIdsToRemove.add(null); + + memberGroup = groupService.removeGroups(memberGroup, groupIdsToRemove); + assert memberGroup.getGroupIds() == null || memberGroup.getGroupIds().isEmpty(); + } + + @Test + void testForbiddenKeywords() { + assert !groupService.registerForbiddenKeywords(null); + assert !groupService.registerForbiddenKeywords(Set.of()); + + assert !groupService.removeForbiddenKeywords(null); + assert !groupService.removeForbiddenKeywords(Set.of()); + + Set keywords = Set.of("keyword1", "keyword2", "keyword3"); + assert !groupService.removeForbiddenKeywords(keywords); + assert groupService.registerForbiddenKeywords(keywords); + + assertThrows(IllegalArgumentException.class, () -> groupService.create(GroupParams.with() + .name(new TextField("keyword1")) + .build())); + + assertThrows(IllegalArgumentException.class, () -> groupService.create(GroupParams.with() + .name(new TextField("keyword2")) + .build())); + + assertThrows(IllegalArgumentException.class, () -> groupService.create(GroupParams.with() + .name(new TextField("keyword3")) + .build())); + + assert groupService.removeForbiddenKeywords(Set.of("keyword1", "keyword2")); + + Group group = groupService.create(GroupParams.with().name(new TextField("keyword1")).build()); + assert group != null; + + group = groupService.create(GroupParams.with().name(new TextField("keyword2")).build()); + assert group != null; + + assertThrows(IllegalArgumentException.class, () -> groupService.create(UserParams.with() + .email(new TextField("keyword3")) + .build())); + + groupService.clearForbiddenKeywords(); + + group = groupService.create(GroupParams.with().name(new TextField("keyword3")).build()); + assert group != null; + } + + private Group createGroup(String name) { + return createGroup(name, new ArrayList<>()); + } + + /** + * @param groupIds Ids of groups to be member of + * */ + private Group createGroup(String name, List groupIds) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(GroupConstants.PROCESS_IDENTIFIER) + .title(name) + .build(); + Case groupCase = workflowService.createCase(createCaseParams).getCase(); + return new Group(dataService.setData(new SetDataParams(groupCase, GroupParams.with() + .name(new TextField(name)) + .parentGroupId(CaseField.withValue(List.of(defaultGroupRunner.getDefaultGroup().getStringId()))) + .groupIds(CaseField.withValue(groupIds)) + .build() + .toDataSet(), null)).getCase()); + } +} diff --git a/src/test/java/com/netgrif/application/engine/authorization/service/RoleAssignmentServiceTest.java b/src/test/java/com/netgrif/application/engine/authorization/service/RoleAssignmentServiceTest.java new file mode 100644 index 00000000000..bc12d34fc52 --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/authorization/service/RoleAssignmentServiceTest.java @@ -0,0 +1,384 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authorization.domain.*; +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.authorization.domain.constants.UserConstants; +import com.netgrif.application.engine.authorization.domain.params.GroupParams; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.authorization.domain.repositories.RoleAssignmentRepository; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.startup.DefaultGroupRunner; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.List; +import java.util.Set; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class RoleAssignmentServiceTest { + + @Autowired + private RoleAssignmentService roleAssignmentService; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private IDataService dataService; + + @Autowired + private IRoleService roleService; + + @Autowired + private DefaultGroupRunner defaultGroupRunner; + + @Autowired + private RoleAssignmentRepository repository; + + @Autowired + private TestHelper helper; + + @BeforeEach + public void beforeEach() { + helper.truncateDbs(); + repository.deleteAll(); + } + + @Test + public void testFindAllByActorIdAndRoleIdIn() { + String actorId = "actorId"; + String roleId1 = "roleId1"; + String roleId2 = "roleId2"; + String roleId3 = "roleId3"; + assignProcessRole(actorId, roleId1); + assignProcessRole(actorId, roleId2); + RoleAssignment assignment3 = assignProcessRole(actorId, roleId3); + + List assignments = roleAssignmentService.findAllByActorIdAndRoleIdIn(actorId, Set.of(roleId1, roleId2)); + + assert assignments.size() == 2; + assert assignments.stream().noneMatch(assignment -> assignment.getStringId().equals(assignment3.getStringId())); + } + + @Test + public void testFindAllByRoleIdIn() { + String actorId = "actorId"; + String roleId1 = "roleId1"; + String roleId2 = "roleId2"; + String roleId3 = "roleId3"; + assignProcessRole(actorId, roleId1); + assignProcessRole(actorId, roleId2); + RoleAssignment assignment3 = assignProcessRole(actorId, roleId3); + + List assignments = roleAssignmentService.findAllByRoleIdIn(Set.of(roleId1, roleId2)); + + assert assignments.size() == 2; + assert assignments.stream().noneMatch(assignment -> assignment.getStringId().equals(assignment3.getStringId())); + } + + @Test + public void testFindAllByActorId() { + String actorId = "actorId"; + String roleId1 = "roleId1"; + String roleId2 = "roleId2"; + assignProcessRole(actorId, roleId1); + assignProcessRole(actorId, roleId2); + + assert roleAssignmentService.findAllByActorId(actorId).size() == 2; + } + + @Test + public void testFindAllRoleIdsByActorId() { + String actorId = "actorId"; + String roleId1 = "roleId1"; + String roleId2 = "roleId2"; + assignProcessRole(actorId, roleId1); + assignProcessRole(actorId, roleId2); + assignProcessRole("otherActorId", "role3"); + + assert roleAssignmentService.findAllRoleIdsByActorId(actorId).size() == 2; + } + + @Test + public void testFindAllRoleIdsByActorAndGroups() { + assert roleAssignmentService.findAllRoleIdsByActorAndGroups(null).isEmpty(); + + Group childGroup = createGroup("child group"); + Group parentGroup = createGroup("parent group"); + childGroup = updateGroupWithParent(childGroup, parentGroup.getStringId()); + Actor actor = createUser("actor@test.com", List.of(childGroup.getStringId())); + + assert roleAssignmentService.findAllRoleIdsByActorAndGroups(actor.getStringId()).isEmpty(); + + updateGroupWithParent(parentGroup, defaultGroupRunner.getDefaultGroup().getStringId()); + assignProcessRole(defaultGroupRunner.getDefaultGroup().getStringId(), roleService.findDefaultRole().getStringId()); + + Set roleIds = roleAssignmentService.findAllRoleIdsByActorAndGroups(actor.getStringId()); + assert roleIds.size() == 1; + assert roleIds.contains(roleService.findDefaultRole().getStringId()); + + String roleId1 = "roleId1"; + String roleId2 = "roleId2"; + assignCaseRole(parentGroup.getStringId(), roleId1, "caseId"); + assignAppRole(childGroup.getStringId(), roleId2, "appRole"); + + roleIds = roleAssignmentService.findAllRoleIdsByActorAndGroups(actor.getStringId()); + assert roleIds.size() == 3; + assert roleIds.contains(roleService.findDefaultRole().getStringId()); + assert roleIds.contains(roleId1); + assert roleIds.contains(roleId2); + } + + @Test + public void testExistsByActorAndRole() { + String actorId = "actorId"; + String roleId1 = "roleId1"; + assignProcessRole(actorId, roleId1); + + assert !roleAssignmentService.existsByActorAndRole("wrongActor", "wrongRole"); + assert !roleAssignmentService.existsByActorAndRole("wrongActor", roleId1); + assert !roleAssignmentService.existsByActorAndRole(actorId, "wrongRole"); + assert roleAssignmentService.existsByActorAndRole(actorId, roleId1); + } + + @Test + public void testFindApplicationAssignmentsByActor() { + String actorId = "actorId"; + assignAppRole(actorId, "some", "appId"); + assignAppRole(actorId, "some", "appId"); + + assert roleAssignmentService.findApplicationAssignmentsByActor("wrongActor").isEmpty(); + assert roleAssignmentService.findApplicationAssignmentsByActor(actorId).size() == 2; + } + + @Test + public void testCreateAssignments() { + List assignments = roleAssignmentService.createAssignments("actorId", + List.of(new ProcessRole("import_id1"), new CaseRole("import_id2", "case_id"))); + + assert repository.findAll().size() == 2; + assert assignments.size() == 2; + } + + @Test + public void testCreateAssignment() { + String actorId = "actorId"; + + ProcessRole processRole = new ProcessRole("import_id1"); + RoleAssignment assignment = roleAssignmentService.createAssignment(actorId, processRole); + assert assignment != null; + assert assignment instanceof ProcessRoleAssignment; + assert assignment.getActorId().equals(actorId); + assert assignment.getRoleId().equals(processRole.getStringId()); + assert assignment.getRoleImportId().equals(processRole.getImportId()); + assert repository.existsById(assignment.getStringId()); + + CaseRole caseRole = new CaseRole("import_id2", "case_id"); + assignment = roleAssignmentService.createAssignment(actorId, caseRole); + assert assignment != null; + assert assignment instanceof CaseRoleAssignment; + assert assignment.getActorId().equals(actorId); + assert assignment.getRoleId().equals(caseRole.getStringId()); + assert assignment.getRoleImportId().equals(caseRole.getImportId()); + assert ((CaseRoleAssignment) assignment).getCaseId().equals(caseRole.getCaseId()); + assert repository.existsById(assignment.getStringId()); + } + + @Test + public void testRemoveAssignments() { + String actorId = "actor_id"; + String processRoleId = "role1"; + String processRoleId2 = "role2"; + String caseRoleId = "role3"; + RoleAssignment processRoleAssignment = new ProcessRoleAssignment(); + processRoleAssignment.setActorId(actorId); + processRoleAssignment.setRoleId(processRoleId); + RoleAssignment processRoleAssignment2 = new ProcessRoleAssignment(); + processRoleAssignment2.setActorId("someOtherActorId"); + processRoleAssignment2.setRoleId(processRoleId2); + CaseRoleAssignment caseRoleAssignment = new CaseRoleAssignment(); + caseRoleAssignment.setActorId(actorId); + caseRoleAssignment.setRoleId(caseRoleId); + repository.saveAll(List.of(processRoleAssignment, processRoleAssignment2, caseRoleAssignment)); + + List removedAssignments = roleAssignmentService.removeAssignments(actorId, + Set.of(processRoleId, caseRoleId, processRoleId2)); + + assert removedAssignments.size() == 2; + assert removedAssignments.stream().noneMatch(assignment -> + assignment.getStringId().equals(processRoleAssignment2.getStringId())); + + List persistedAssignments = repository.findAll(); + assert persistedAssignments.size() == 1; + assert persistedAssignments.get(0).getStringId().equals(processRoleAssignment2.getStringId()); + } + + @Test + public void testRemoveAssignment() { + String actorId = "actor_id"; + String roleId = "role1"; + assignProcessRole(actorId, roleId); + + assert repository.count() == 1; + roleAssignmentService.removeAssignment(actorId, roleId); + assert repository.count() == 0; + } + + @Test + public void testRemoveAssignmentsByActor() { + String actorId = "actor_id"; + String processRoleId = "role1"; + String processRoleId2 = "role2"; + String caseRoleId = "role3"; + assignProcessRole(actorId, processRoleId); + RoleAssignment processRoleAssignment2 = assignProcessRole("someOtherActorId", processRoleId2); + assignCaseRole(actorId, caseRoleId, "caseId"); + + assert repository.count() == 3; + List removedAssignments = roleAssignmentService.removeAssignmentsByActor(actorId); + + assert removedAssignments.size() == 2; + assert removedAssignments.stream().noneMatch(assignment -> + assignment.getStringId().equals(processRoleAssignment2.getStringId())); + + List persistedAssignments = repository.findAll(); + assert persistedAssignments.size() == 1; + assert persistedAssignments.get(0).getStringId().equals(processRoleAssignment2.getStringId()); + } + + @Test + public void testRemoveAssignmentsByRole() { + String roleId = "role1"; + String roleId2 = "role2"; + RoleAssignment assignment = new ProcessRoleAssignment(); + assignment.setRoleId(roleId); + RoleAssignment assignment2 = new ProcessRoleAssignment(); + assignment2.setRoleId(roleId2); + RoleAssignment assignment3 = new ProcessRoleAssignment(); + assignment3.setRoleId(roleId); + repository.saveAll(List.of(assignment, assignment2, assignment3)); + + List removedAssignments = roleAssignmentService.removeAssignmentsByRole(roleId); + + List persistedAssignments = repository.findAll(); + assert persistedAssignments.size() == 1; + assert persistedAssignments.get(0).getStringId().equals(assignment2.getStringId()); + + assert removedAssignments.size() == 2; + assert removedAssignments.stream().noneMatch(removedAssignment -> + removedAssignment.getStringId().equals(assignment2.getStringId())); + } + + @Test + public void testRemoveAssignmentsByRoles() { + String roleId = "role1"; + String roleId2 = "role2"; + String roleId3 = "role3"; + RoleAssignment assignment = new ProcessRoleAssignment(); + assignment.setRoleId(roleId); + RoleAssignment assignment2 = new ProcessRoleAssignment(); + assignment2.setRoleId(roleId2); + RoleAssignment assignment3 = new CaseRoleAssignment(); + assignment3.setRoleId(roleId3); + repository.saveAll(List.of(assignment, assignment2, assignment3)); + + List removedAssignments = roleAssignmentService.removeAssignmentsByRoles(Set.of(roleId, roleId2)); + + List persistedAssignments = repository.findAll(); + assert persistedAssignments.size() == 1; + assert persistedAssignments.get(0).getStringId().equals(assignment3.getStringId()); + + assert removedAssignments.size() == 2; + assert removedAssignments.stream().noneMatch(removedAssignment -> + removedAssignment.getStringId().equals(assignment3.getStringId())); + } + + @Test + public void testRemoveAssignmentsByCase() { + String caseId = "case_id"; + CaseRoleAssignment caseRoleAssignment = new CaseRoleAssignment(); + caseRoleAssignment.setCaseId(caseId); + RoleAssignment processRoleAssignment = new ProcessRoleAssignment(); + repository.saveAll(List.of(processRoleAssignment, caseRoleAssignment)); + + List removedAssignments = roleAssignmentService.removeAssignmentsByCase(caseId); + + List persistedAssignments = repository.findAll(); + assert persistedAssignments.size() == 1; + assert persistedAssignments.get(0).getStringId().equals(processRoleAssignment.getStringId()); + + assert removedAssignments.size() == 1; + assert removedAssignments.stream().noneMatch(removedAssignment -> + removedAssignment.getStringId().equals(processRoleAssignment.getStringId())); + } + + private Group createGroup(String name) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(GroupConstants.PROCESS_IDENTIFIER) + .title(name) + .build(); + Case groupCase = workflowService.createCase(createCaseParams).getCase(); + return new Group(dataService.setData(new SetDataParams(groupCase, GroupParams.with() + .name(new TextField(name)) + .build() + .toDataSet(), null)).getCase()); + } + + private Group updateGroupWithParent(Group group, String parentGroupId) { + return new Group(dataService.setData(new SetDataParams(group.getCase(), GroupParams.with() + .parentGroupId(CaseField.withValue(List.of(parentGroupId))) + .build() + .toDataSet(), null)).getCase()); + } + + private User createUser(String email, List additionalGroupIds) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(UserConstants.PROCESS_IDENTIFIER) + .title(email) + .build(); + Case userCase = workflowService.createCase(createCaseParams).getCase(); + return new User(dataService.setData(new SetDataParams(userCase, UserParams.with() + .email(new TextField(email)) + .groupIds(CaseField.withValue(additionalGroupIds)) + .build() + .toDataSet(), null)).getCase()); + } + + private RoleAssignment assignProcessRole(String actorId, String roleId) { + RoleAssignment assignment = new ProcessRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(roleId); + return repository.save(assignment); + } + + private RoleAssignment assignCaseRole(String actorId, String roleId, String caseId) { + CaseRoleAssignment assignment = new CaseRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(roleId); + assignment.setCaseId(caseId); + return repository.save(assignment); + } + + private RoleAssignment assignAppRole(String actorId, String roleId, String appId) { + ApplicationRoleAssignment assignment = new ApplicationRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(roleId); + assignment.setApplicationId(appId); + return repository.save(assignment); + } +} diff --git a/src/test/java/com/netgrif/application/engine/authorization/service/RoleServiceTest.java b/src/test/java/com/netgrif/application/engine/authorization/service/RoleServiceTest.java new file mode 100644 index 00000000000..9c4a68a6f21 --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/authorization/service/RoleServiceTest.java @@ -0,0 +1,504 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authorization.domain.*; +import com.netgrif.application.engine.authorization.domain.constants.UserConstants; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.authorization.domain.permissions.AccessPermissions; +import com.netgrif.application.engine.authorization.domain.permissions.CasePermission; +import com.netgrif.application.engine.authorization.domain.permissions.TaskPermission; +import com.netgrif.application.engine.authorization.domain.repositories.RoleAssignmentRepository; +import com.netgrif.application.engine.authorization.domain.repositories.RoleRepository; +import com.netgrif.application.engine.history.domain.baseevent.EventLog; +import com.netgrif.application.engine.history.domain.baseevent.repository.EventLogRepository; +import com.netgrif.application.engine.history.domain.actorevents.ActorAssignRoleEventLog; +import com.netgrif.application.engine.history.domain.actorevents.ActorRemoveRoleEventLog; +import com.netgrif.application.engine.petrinet.domain.I18nString; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.UserField; +import com.netgrif.application.engine.petrinet.domain.dataset.UserListField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.startup.ImportHelper; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.Task; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class RoleServiceTest { + + @Autowired + private TestHelper helper; + + @Autowired + private RoleRepository repository; + + @Autowired + private RoleAssignmentRepository assignmentRepository; + + @Autowired + private EventLogRepository eventLogRepository; + + @Autowired + private RoleService roleService; + + @Autowired + private ImportHelper importHelper; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private IDataService dataService; + + @BeforeEach + public void beforeEach() { + helper.truncateDbs(); + repository.deleteAll(); + roleService.clearCache(); + } + + @Test + public void testFindAll() { + Role processRole = new ProcessRole("import_id1"); + Role caseRole = new CaseRole("import_id2", "case_id"); + repository.saveAll(List.of(processRole, caseRole)); + + assert roleService.findAll().size() == 2; + } + + @Test + public void testFindAllById() { + Role processRole1 = new ProcessRole("import_id1"); + Role processRole2 = new ProcessRole("import_id2"); + Role caseRole = new CaseRole("import_id3", "case_id"); + repository.saveAll(List.of(processRole1, processRole2, caseRole)); + + List foundRoles = roleService.findAllById(Set.of(processRole1.getStringId(), caseRole.getStringId())); + assert foundRoles.size() == 2; + + Set foundRoleIds = foundRoles.stream().map(Role::getStringId).collect(Collectors.toSet()); + assert foundRoleIds.contains(processRole1.getStringId()); + assert !foundRoleIds.contains(processRole2.getStringId()); + assert foundRoleIds.contains(caseRole.getStringId()); + + assert roleService.findAllById(Set.of()).isEmpty(); + } + + @Test + public void testFindAllRoleIdsByActorAndGroups() { + Set emptySet = roleService.findAllRoleIdsByActorAndGroups(null); + assert emptySet != null && emptySet.isEmpty(); + + User testUser = createUser("test@user.com"); + + String processRoleId = "role1"; + String caseRoleId = "role3"; + RoleAssignment processRoleAssignment = new ProcessRoleAssignment(); + processRoleAssignment.setActorId(testUser.getStringId()); + processRoleAssignment.setRoleId(processRoleId); + CaseRoleAssignment caseRoleAssignment = new CaseRoleAssignment(); + caseRoleAssignment.setActorId(testUser.getStringId()); + caseRoleAssignment.setRoleId(caseRoleId); + assignmentRepository.saveAll(List.of(processRoleAssignment, caseRoleAssignment)); + + Set roleIds = roleService.findAllRoleIdsByActorAndGroups(testUser.getStringId()); + assert roleIds != null; + assert roleIds.size() == 2; + assert roleIds.contains(processRoleId); + assert roleIds.contains(caseRoleId); + } + + @Test + public void testFindDefaultRole() { + Role defaultRole = roleService.findDefaultRole(); + assert defaultRole != null; + assert defaultRole.getImportId().equals(ProcessRole.DEFAULT_ROLE); + } + + @Test + public void testFindAnonymousRole() { + Role anonymousRole = roleService.findAnonymousRole(); + assert anonymousRole != null; + assert anonymousRole.getImportId().equals(ProcessRole.ANONYMOUS_ROLE); + } + + @Test + public void testFindAllApplicationRoles() { + Role processRole1 = new ProcessRole("import_id1"); + Role appRole1 = new ApplicationRole("import_id2", "application1"); + Role appRole2 = new ApplicationRole("import_id3", "application1"); + Role caseRole = new CaseRole("import_id4", "case_id"); + repository.saveAll(List.of(processRole1, appRole1, appRole2, caseRole)); + + List appRoles = roleService.findAllApplicationRoles(); + assert appRoles.size() == 2; + assert appRoles.stream().allMatch(role -> role.getStringId().equals(appRole1.getStringId()) + || role.getStringId().equals(appRole2.getStringId())); + } + + @Test + public void testExistsApplicationRoleByImportId() { + Role appRole = new ApplicationRole("import_id1", "application1"); + Role caseRole = new CaseRole("import_id2", "case_id"); + Role processRole = new ProcessRole("import_id3"); + repository.saveAll(List.of(appRole, caseRole, processRole)); + + assert roleService.existsApplicationRoleByImportId(appRole.getImportId()); + assert !roleService.existsApplicationRoleByImportId(caseRole.getImportId()); + assert !roleService.existsApplicationRoleByImportId(processRole.getImportId()); + } + + @Test + public void testFindApplicationRoleByImportId() { + Role appRole = new ApplicationRole("import_id1", "application1"); + Role caseRole = new CaseRole("import_id2", "case_id"); + Role processRole = new ProcessRole("import_id3"); + repository.saveAll(List.of(appRole, caseRole, processRole)); + + assert roleService.findApplicationRoleByImportId(appRole.getImportId()) != null; + assert roleService.findApplicationRoleByImportId(caseRole.getImportId()) == null; + assert roleService.findApplicationRoleByImportId(processRole.getImportId()) == null; + } + + @Test + public void testFindAllProcessRoles() { + Role processRole1 = new ProcessRole("import_id1"); + Role processRole2 = new ProcessRole("import_id2"); + Role caseRole = new CaseRole("import_id3", "case_id"); + repository.saveAll(List.of(processRole1, processRole2, caseRole)); + + List processRoles = roleService.findAllProcessRoles(); + assert processRoles.size() == 2; + assert processRoles.stream().noneMatch(role -> role.getStringId().equals(caseRole.getStringId())); + } + + @Test + public void testFindAllProcessRolesByImportIds() { + Role processRole1 = new ProcessRole("import_id1"); + Role processRole2 = new ProcessRole("import_id2"); + Role caseRole = new CaseRole("import_id1", "case_id"); + repository.saveAll(List.of(processRole1, processRole2, caseRole)); + + List processRoles = roleService.findAllProcessRolesByImportIds(Set.of("import_id1", "import_id2")); + assert processRoles.size() == 2; + assert processRoles.stream().noneMatch(role -> role.getStringId().equals(caseRole.getStringId())); + } + + @Test + public void testFindProcessRolesByDefaultTitle() { + ProcessRole processRole1 = new ProcessRole("import_id1"); + processRole1.setTitle(new I18nString("testTitle")); + ProcessRole processRole2 = new ProcessRole("import_id2"); + processRole2.setTitle(new I18nString("testTitle")); + ProcessRole processRole3 = new ProcessRole("import_id3"); + processRole3.setTitle(new I18nString("otherTitle")); + repository.saveAll(List.of(processRole1, processRole2, processRole3)); + + List processRoles = roleService.findProcessRolesByDefaultTitle("testTitle"); + assert processRoles.size() == 2; + assert processRoles.stream().noneMatch(role -> role.getStringId().equals(processRole3.getStringId())); + } + + @Test + public void testExistsProcessRoleByImportId() { + Role processRole = new ProcessRole("import_id1"); + Role caseRole = new CaseRole("import_id2", "case_id"); + Role appRole = new ApplicationRole("import_id3", "application_id"); + repository.saveAll(List.of(processRole, caseRole, appRole)); + + assert roleService.existsProcessRoleByImportId(processRole.getImportId()); + assert !roleService.existsProcessRoleByImportId(caseRole.getImportId()); + assert !roleService.existsProcessRoleByImportId(appRole.getImportId()); + } + + @Test + public void testFindProcessRoleByImportId() { + Role processRole = new ProcessRole("import_id1"); + Role caseRole = new CaseRole("import_id2", "case_id"); + Role appRole = new ApplicationRole("import_id3", "application_id"); + repository.saveAll(List.of(processRole, caseRole, appRole)); + + assert roleService.findProcessRoleByImportId(processRole.getImportId()) != null; + assert roleService.findProcessRoleByImportId(caseRole.getImportId()) == null; + assert roleService.findProcessRoleByImportId(appRole.getImportId()) == null; + } + + @Test + public void testFindAllCaseRoles() { + Role caseRole1 = new CaseRole("import_id1", "case_id"); + Role caseRole2 = new CaseRole("import_id2", "case_id"); + Role processRole = new ProcessRole("import_id3"); + repository.saveAll(List.of(processRole, caseRole1, caseRole2)); + + List caseRoles = roleService.findAllCaseRoles(); + assert caseRoles.size() == 2; + assert caseRoles.stream().noneMatch(role -> role.getStringId().equals(processRole.getStringId())); + } + + @Test + public void testFindCaseRoleByCaseIdAndImportId() { + CaseRole caseRole1 = new CaseRole("import_id1", "case_id"); + Role caseRole2 = new CaseRole("import_id2", "case_id"); + Role processRole = new ProcessRole("import_id1"); + repository.saveAll(List.of(processRole, caseRole1, caseRole2)); + + CaseRole foundCaseRole = roleService.findCaseRoleByCaseIdAndImportId("case_id", "import_id1"); + assert foundCaseRole.getImportId().equals(caseRole1.getImportId()); + assert foundCaseRole.getCaseId().equals(caseRole1.getCaseId()); + } + + @Test + public void testSave() { + assert roleService.save(new ProcessRole("import_id")).getId() != null; + assert roleService.save(new CaseRole("import_id", "case_id")).getId() != null; + assert roleService.save(new ApplicationRole("import_id", "application_id")).getId() != null; + } + + @Test + public void testSaveAll() { + List roles = List.of(new ProcessRole("import_id"), new CaseRole("import_id", "case_id"), + new ApplicationRole("import_id", "application_id")); + assert roleService.saveAll(roles).size() == 3; + } + + @Test + public void testRemove() { + Role processRole1 = new ProcessRole("import_id1"); + Role processRole2 = new ProcessRole("import_id2"); + Role caseRole = new CaseRole("import_id3", "case_id"); + repository.saveAll(List.of(processRole1, processRole2, caseRole)); + + assert repository.findAll().size() == 3; + roleService.remove(processRole1); + List roles = repository.findAll(); + assert roles.stream().map(Role::getStringId).noneMatch(roleId -> roleId.equals(processRole1.getStringId())); + } + + @Test + public void testRemoveAll() { + Role processRole1 = new ProcessRole("import_id1"); + Role processRole2 = new ProcessRole("import_id2"); + Role caseRole = new CaseRole("import_id3", "case_id"); + repository.saveAll(List.of(processRole1, processRole2, caseRole)); + + assert repository.findAll().size() == 3; + roleService.removeAll(List.of(processRole1, caseRole)); + List roles = repository.findAll(); + assert roles.size() == 1; + assert roles.get(0).getStringId().equals(processRole2.getStringId()); + } + + @Test + public void testRemoveAllByCase() { + String caseId = new ObjectId().toString(); + Role caseRole1 = new CaseRole("import_id2", caseId); + Role caseRole2 = new CaseRole("import_id3", caseId); + Role caseRole3 = new CaseRole("import_id4", "fancyCaseId"); + repository.saveAll(List.of(caseRole1, caseRole2, caseRole3)); + + assert roleService.findAll().size() == 3; + roleService.removeAllByCase(caseId); + assert roleService.findAll().size() == 1; + } + + @Test + public void testResolveCaseRolesOnCase() { + UserListField userListField = new UserListField(); + userListField.setImportId("actor_list_id"); + UserField userField = new UserField(); + userField.setImportId("actor_id"); + + Case useCase = new Case(); + useCase.getDataSet().put(userListField.getImportId(), userListField); + useCase.getDataSet().put(userField.getImportId(), userField); + + AccessPermissions netPermissions = new AccessPermissions<>(); + netPermissions.addPermission(userListField.getImportId(), CasePermission.VIEW, true); + netPermissions.addPermission(userField.getImportId(), CasePermission.VIEW, true); + + roleService.resolveCaseRolesOnCase(useCase, netPermissions, false); + + List roles = roleService.findAllCaseRoles(); + assert roles.size() == 2; + assert roles.stream().allMatch(role -> role.getCaseId().equals(useCase.getStringId())); + Optional userFieldCaseRoleOpt = roles.stream() + .filter(role -> role.getImportId().equals(userField.getImportId())) + .findFirst(); + assert userFieldCaseRoleOpt.isPresent(); + Optional userListFieldCaseRoleOpt = roles.stream() + .filter(role -> role.getImportId().equals(userListField.getImportId())) + .findFirst(); + assert userListFieldCaseRoleOpt.isPresent(); + + assert userField.getCaseRoleIds().size() == 1; + assert userField.getCaseRoleIds().contains(userFieldCaseRoleOpt.get().getStringId()); + assert userListField.getCaseRoleIds().size() == 1; + assert userListField.getCaseRoleIds().contains(userListFieldCaseRoleOpt.get().getStringId()); + assert useCase.getCaseRolePermissions().containsKey(userFieldCaseRoleOpt.get().getStringId()); + assert useCase.getCaseRolePermissions().containsKey(userListFieldCaseRoleOpt.get().getStringId()); + + Case emptyUseCase = new Case(); + emptyUseCase.setPetriNetObjectId(new ObjectId()); + AccessPermissions invalidNetPermissions = new AccessPermissions<>(); + invalidNetPermissions.addPermission("nonExistingFieldId", CasePermission.VIEW, true); + assertThrows(IllegalStateException.class, () -> + roleService.resolveCaseRolesOnCase(emptyUseCase, invalidNetPermissions, false)); + } + + @Test + public void testResolveCaseRolesOnTask() { + UserListField userListField = new UserListField(); + userListField.setImportId("actor_list_id"); + UserField userField = new UserField(); + userField.setImportId("actor_id"); + + Task task = Task.with().transitionId("transition_id").build(); + + Case useCase = new Case(); + useCase.getDataSet().put(userListField.getImportId(), userListField); + useCase.getDataSet().put(userField.getImportId(), userField); + useCase.addTask(task); + + AccessPermissions transitionPermissions = new AccessPermissions<>(); + transitionPermissions.addPermission(userListField.getImportId(), TaskPermission.VIEW, true); + transitionPermissions.addPermission(userField.getImportId(), TaskPermission.VIEW, true); + + roleService.resolveCaseRolesOnTask(useCase, task, transitionPermissions, false, false); + + List roles = roleService.findAllCaseRoles(); + assert roles.size() == 2; + assert roles.stream().allMatch(role -> role.getCaseId().equals(useCase.getStringId())); + Optional userFieldCaseRoleOpt = roles.stream() + .filter(role -> role.getImportId().equals(userField.getImportId())) + .findFirst(); + assert userFieldCaseRoleOpt.isPresent(); + Optional userListFieldCaseRoleOpt = roles.stream() + .filter(role -> role.getImportId().equals(userListField.getImportId())) + .findFirst(); + assert userListFieldCaseRoleOpt.isPresent(); + + assert userField.getCaseRoleIds().size() == 1; + assert userField.getCaseRoleIds().contains(userFieldCaseRoleOpt.get().getStringId()); + assert userListField.getCaseRoleIds().size() == 1; + assert userListField.getCaseRoleIds().contains(userListFieldCaseRoleOpt.get().getStringId()); + assert useCase.getCaseRolePermissions().isEmpty(); + assert task.getCaseRolePermissions().containsKey(userFieldCaseRoleOpt.get().getStringId()); + assert task.getCaseRolePermissions().containsKey(userListFieldCaseRoleOpt.get().getStringId()); + } + + @Test + public void testAssignRolesToActor() { + Identity identity = importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .password(new TextField("password")) + .username(new TextField("email@email.com")) + .build(), new ArrayList<>()); + + Role processRole = new ProcessRole("import_id1"); + Role caseRole = new CaseRole("import_id2", "case_id"); + repository.saveAll(List.of(processRole, caseRole)); + + eventLogRepository.deleteAll(); + List assignedRoles = roleService.assignRolesToActor(identity.toSession().getActiveActorId(), + Set.of(processRole.getStringId(), caseRole.getStringId())); + + assert assignedRoles.size() == 2; + assert assignedRoles.stream().anyMatch(role -> role.getStringId().equals(processRole.getStringId())); + assert assignedRoles.stream().anyMatch(role -> role.getStringId().equals(caseRole.getStringId())); + List eventLogs = eventLogRepository.findAll(); + assert eventLogs.size() == 1; + ActorAssignRoleEventLog eventLogAfterFirstAssign = (ActorAssignRoleEventLog) eventLogs.get(0); + assert eventLogAfterFirstAssign.getRoles().size() == 2; + + Role processRole2 = new ProcessRole("import_id3"); + repository.save(processRole2); + assignedRoles = roleService.assignRolesToActor(identity.toSession().getActiveActorId(), + Set.of(processRole.getStringId(), processRole2.getStringId())); + + assert assignedRoles.size() == 1; + assert assignedRoles.get(0).getStringId().equals(processRole2.getStringId()); + eventLogs = eventLogRepository.findAll(); + assert eventLogs.size() == 2; + Optional eventLogAfterSecondAssignOpt = eventLogs.stream() + .filter(log -> !log.getStringId().equals(eventLogAfterFirstAssign.getStringId())) + .findFirst(); + assert eventLogAfterSecondAssignOpt.isPresent(); + assert ((ActorAssignRoleEventLog) eventLogAfterSecondAssignOpt.get()).getRoles().size() == 1; + + Role processRole3 = new ProcessRole("import_id4"); + repository.save(processRole3); + assertThrows(IllegalArgumentException.class, () -> roleService.assignRolesToActor(identity.toSession().getActiveActorId(), + Set.of("nonExistingId", processRole3.getStringId()))); + + assertThrows(IllegalArgumentException.class, () -> roleService.assignRolesToActor("nonExistingId", + Set.of(processRole3.getStringId()))); + } + + @Test + public void testRemoveRolesFromActor() { + Identity identity = importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .password(new TextField("password")) + .username(new TextField("email@email.com")) + .build(), new ArrayList<>()); + Role processRole = new ProcessRole("import_id1"); + Role processRole2 = new ProcessRole("import_id2"); + Role caseRole = new CaseRole("import_id3", "case_id"); + repository.saveAll(List.of(processRole, processRole2, caseRole)); + roleService.assignRolesToActor(identity.toSession().getActiveActorId(), Set.of(processRole.getStringId(), + caseRole.getStringId())); + + eventLogRepository.deleteAll(); + List removedRoles = roleService.removeRolesFromActor(identity.toSession().getActiveActorId(), + Set.of(processRole.getStringId(), processRole2.getStringId())); + assert removedRoles.size() == 1; + assert removedRoles.get(0).getStringId().equals(processRole.getStringId()); + List eventLogs = eventLogRepository.findAll(); + assert eventLogs.size() == 1; + ActorRemoveRoleEventLog eventLogAfterFirstRemoval = (ActorRemoveRoleEventLog) eventLogs.get(0); + assert eventLogAfterFirstRemoval.getRoles().size() == 1; + + assertThrows(IllegalArgumentException.class, () -> roleService.removeRolesFromActor(identity.toSession().getActiveActorId(), + Set.of("nonExistingId"))); + + assertThrows(IllegalArgumentException.class, () -> roleService.assignRolesToActor("nonExistingId", + Set.of(caseRole.getStringId()))); + } + + private User createUser(String email) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(UserConstants.PROCESS_IDENTIFIER) + .title(email) + .build(); + Case userCase = workflowService.createCase(createCaseParams).getCase(); + return new User(dataService.setData(new SetDataParams(userCase, UserParams.with() + .email(new TextField(email)) + .build() + .toDataSet(), null)).getCase()); + } +} diff --git a/src/test/java/com/netgrif/application/engine/authorization/service/TaskAuthorizationServiceTest.java b/src/test/java/com/netgrif/application/engine/authorization/service/TaskAuthorizationServiceTest.java new file mode 100644 index 00000000000..3ef41f1c83f --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/authorization/service/TaskAuthorizationServiceTest.java @@ -0,0 +1,780 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authorization.domain.*; +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.authorization.domain.params.GroupParams; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.authorization.domain.repositories.CaseRoleRepository; +import com.netgrif.application.engine.authorization.domain.repositories.ProcessRoleRepository; +import com.netgrif.application.engine.authorization.domain.repositories.RoleAssignmentRepository; +import com.netgrif.application.engine.authorization.service.interfaces.IGroupService; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; +import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.petrinet.domain.VersionType; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; +import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; +import com.netgrif.application.engine.startup.ImportHelper; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.State; +import com.netgrif.application.engine.workflow.domain.Task; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +class TaskAuthorizationServiceTest { + + @Autowired + private TaskAuthorizationService authorizationService; + + @Autowired + private ISessionManagerService sessionManagerService; + + @Autowired + private IPetriNetService petriNetService; + + @Autowired + private ITaskService taskService; + + @Autowired + private RoleAssignmentRepository roleAssignmentRepository; + + @Autowired + private ProcessRoleRepository processRoleRepository; + + @Autowired + private CaseRoleRepository caseRoleRepository; + + @Autowired + private ApplicationRoleRunner applicationRoleRunner; + + @Autowired + private ImportHelper importHelper; + + @Autowired + private TestHelper testHelper; + + @Autowired + private IUserService userService; + + @Autowired + private IGroupService groupService; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private IDataService dataService; + + private Identity testIdentity; + + private Group testGroup; + + private Case testCase; + + private Case testCaseWithDefault; + + @BeforeEach + public void beforeEach() throws IOException, MissingPetriNetMetaDataException { + testHelper.truncateDbs(); + + testIdentity = importHelper.createIdentity(IdentityParams.with() + .username(new TextField("username")) + .password(new TextField("password")) + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .build(), new ArrayList<>()); + + Process testProcess = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/petriNets/task_authorization_test.xml"), + VersionType.MAJOR, userService.getSystemUser().getStringId())).getProcess(); + Process testProcessWithDefault = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/petriNets/task_authorization_default_test.xml"), + VersionType.MAJOR, userService.getSystemUser().getStringId())).getProcess(); + + TestHelper.login(testIdentity); + + testCase = importHelper.createCase("test", testProcess); + testCaseWithDefault = importHelper.createCase("test with default role", testProcessWithDefault); + } + + @Test + void canCallAssign() { + // order of assertions is important! + assert !authorizationService.canCallAssign(null); + assert !authorizationService.canCallAssign("wrong id"); + + String taskId = testCase.getTaskStringId("t_assign"); + + assert !authorizationService.canCallAssign(taskId); + assert authorizationService.canCallAssign(testCaseWithDefault.getTaskStringId("t_assign")); + + ProcessRole posProcessRole = processRoleRepository.findByImportId("pos_process_role"); + assignProcessRole(testIdentity.getMainActorId(), posProcessRole); + assert authorizationService.canCallAssign(taskId); + + updateAssigneeOfTask(taskId, new ObjectId().toString()); + assert !authorizationService.canCallAssign(taskId); + updateAssigneeOfTask(taskId, null); + + ProcessRole negProcessRole = processRoleRepository.findByImportId("neg_process_role"); + assignProcessRole(testIdentity.getMainActorId(), negProcessRole); + assert !authorizationService.canCallAssign(taskId); + + CaseRole posCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_case_role"); + assignCaseRole(testIdentity.getMainActorId(), posCaseRole); + assert authorizationService.canCallAssign(taskId); + + CaseRole negCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_case_role"); + assignCaseRole(testIdentity.getMainActorId(), negCaseRole); + assert !authorizationService.canCallAssign(taskId); + + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + assignAppRole(testIdentity.getMainActorId(), adminAppRole); + assert authorizationService.canCallAssign(taskId); + + TestHelper.logout(); + assert !authorizationService.canCallAssign(taskId); + } + + @Test + void canCallAssignByGroups() { + // order of assertions is important! + User testUser = initializeTestUserWithGroup(); + + assert !roleAssignmentRepository.findAllByActorId(testUser.getStringId()).iterator().hasNext(); + + assert !authorizationService.canCallAssign(null); + + String taskId = testCase.getTaskStringId("t_assign"); + + assert !authorizationService.canCallAssign(taskId); + assert !authorizationService.canCallAssign(testCaseWithDefault.getTaskStringId("t_assign")); + + testGroup = updateGroupWithParent(testGroup, groupService.getDefaultGroup().getStringId()); + + assert !authorizationService.canCallAssign(taskId); + assert authorizationService.canCallAssign(testCaseWithDefault.getTaskStringId("t_assign")); + + ProcessRole posProcessRole = processRoleRepository.findByImportId("pos_process_role"); + assignProcessRole(testGroup.getStringId(), posProcessRole); + assert authorizationService.canCallAssign(taskId); + + updateAssigneeOfTask(taskId, new ObjectId().toString()); + assert !authorizationService.canCallAssign(taskId); + updateAssigneeOfTask(taskId, null); + + ProcessRole negProcessRole = processRoleRepository.findByImportId("neg_process_role"); + assignProcessRole(testGroup.getStringId(), negProcessRole); + assert !authorizationService.canCallAssign(taskId); + + CaseRole posCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_case_role"); + assignCaseRole(testGroup.getStringId(), posCaseRole); + assert authorizationService.canCallAssign(taskId); + + CaseRole negCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_case_role"); + assignCaseRole(testGroup.getStringId(), negCaseRole); + assert !authorizationService.canCallAssign(taskId); + + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + assignAppRole(testGroup.getStringId(), adminAppRole); + assert authorizationService.canCallAssign(taskId); + + TestHelper.logout(); + assert !authorizationService.canCallAssign(taskId); + } + + @Test + public void canCallCancel() { + // order of assertions is important! + assert !authorizationService.canCallCancel(null); + assert !authorizationService.canCallCancel("wrong id"); + + String taskId = testCase.getTaskStringId("t_cancel"); + String taskIdWithDefault = testCaseWithDefault.getTaskStringId("t_cancel"); + + assert !authorizationService.canCallCancel(taskId); + + updateAssigneeOfTask(taskIdWithDefault, sessionManagerService.getActiveActorId()); + assert authorizationService.canCallCancel(taskIdWithDefault); + + updateAssigneeOfTask(taskId, new ObjectId().toString()); + assert !authorizationService.canCallCancel(taskId); + + ProcessRole posProcessRole = processRoleRepository.findByImportId("pos_process_role"); + assignProcessRole(testIdentity.getMainActorId(), posProcessRole); + assert !authorizationService.canCallCancel(taskId); + + updateAssigneeOfTask(taskId, sessionManagerService.getActiveActorId()); + assert authorizationService.canCallCancel(taskId); + + ProcessRole negProcessRole = processRoleRepository.findByImportId("neg_process_role"); + assignProcessRole(testIdentity.getMainActorId(), negProcessRole); + assert !authorizationService.canCallCancel(taskId); + + CaseRole posCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_case_role"); + assignCaseRole(testIdentity.getMainActorId(), posCaseRole); + assert authorizationService.canCallCancel(taskId); + + CaseRole negCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_case_role"); + assignCaseRole(testIdentity.getMainActorId(), negCaseRole); + assert !authorizationService.canCallCancel(taskId); + + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + assignAppRole(testIdentity.getMainActorId(), adminAppRole); + assert authorizationService.canCallCancel(taskId); + + TestHelper.logout(); + assert !authorizationService.canCallCancel(taskId); + } + + @Test + public void canCallCancelByGroups() { + // order of assertions is important! + User testUser = initializeTestUserWithGroup(); + + assert !roleAssignmentRepository.findAllByActorId(testUser.getStringId()).iterator().hasNext(); + + assert !authorizationService.canCallCancel(null); + + String taskId = testCase.getTaskStringId("t_cancel"); + String taskIdWithDefault = testCaseWithDefault.getTaskStringId("t_cancel"); + + assert !authorizationService.canCallCancel(taskId); + updateAssigneeOfTask(taskIdWithDefault, sessionManagerService.getActiveActorId()); + assert !authorizationService.canCallCancel(taskIdWithDefault); + + testGroup = updateGroupWithParent(testGroup, groupService.getDefaultGroup().getStringId()); + + assert !authorizationService.canCallCancel(taskId); + assert authorizationService.canCallCancel(taskIdWithDefault); + + updateAssigneeOfTask(taskId, new ObjectId().toString()); + assert !authorizationService.canCallCancel(taskId); + + ProcessRole posProcessRole = processRoleRepository.findByImportId("pos_process_role"); + assignProcessRole(testGroup.getStringId(), posProcessRole); + assert !authorizationService.canCallCancel(taskId); + + updateAssigneeOfTask(taskId, sessionManagerService.getActiveActorId()); + assert authorizationService.canCallCancel(taskId); + + ProcessRole negProcessRole = processRoleRepository.findByImportId("neg_process_role"); + assignProcessRole(testGroup.getStringId(), negProcessRole); + assert !authorizationService.canCallCancel(taskId); + + CaseRole posCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_case_role"); + assignCaseRole(testGroup.getStringId(), posCaseRole); + assert authorizationService.canCallCancel(taskId); + + CaseRole negCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_case_role"); + assignCaseRole(testGroup.getStringId(), negCaseRole); + assert !authorizationService.canCallCancel(taskId); + + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + assignAppRole(testGroup.getStringId(), adminAppRole); + assert authorizationService.canCallCancel(taskId); + + TestHelper.logout(); + assert !authorizationService.canCallCancel(taskId); + } + + @Test + public void canCallReassign() { + // order of assertions is important! + assert !authorizationService.canCallReassign(null); + assert !authorizationService.canCallReassign("wrong id"); + + String taskId = testCase.getTaskStringId("t_reassign"); + String taskIdWithDefault = testCaseWithDefault.getTaskStringId("t_reassign"); + + assert !authorizationService.canCallReassign(taskId); + + updateAssigneeOfTask(taskIdWithDefault, new ObjectId().toString()); + assert authorizationService.canCallReassign(taskIdWithDefault); + + updateAssigneeOfTask(taskId, new ObjectId().toString()); + assert !authorizationService.canCallReassign(taskId); + + ProcessRole posProcessRole = processRoleRepository.findByImportId("pos_process_role"); + assignProcessRole(testIdentity.getMainActorId(), posProcessRole); + assert authorizationService.canCallReassign(taskId); + + ProcessRole negProcessRole = processRoleRepository.findByImportId("neg_process_role"); + assignProcessRole(testIdentity.getMainActorId(), negProcessRole); + assert !authorizationService.canCallReassign(taskId); + + CaseRole posCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_case_role"); + assignCaseRole(testIdentity.getMainActorId(), posCaseRole); + assert authorizationService.canCallReassign(taskId); + + CaseRole negCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_case_role"); + assignCaseRole(testIdentity.getMainActorId(), negCaseRole); + assert !authorizationService.canCallReassign(taskId); + + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + assignAppRole(testIdentity.getMainActorId(), adminAppRole); + assert authorizationService.canCallReassign(taskId); + + TestHelper.logout(); + assert !authorizationService.canCallReassign(taskId); + } + + @Test + public void canCallReassignByGroups() { + // order of assertions is important! + User testUser = initializeTestUserWithGroup(); + + assert !roleAssignmentRepository.findAllByActorId(testUser.getStringId()).iterator().hasNext(); + + assert !authorizationService.canCallReassign(null); + + String taskId = testCase.getTaskStringId("t_reassign"); + String taskIdWithDefault = testCaseWithDefault.getTaskStringId("t_reassign"); + + assert !authorizationService.canCallReassign(taskId); + updateAssigneeOfTask(taskIdWithDefault, new ObjectId().toString()); + assert !authorizationService.canCallReassign(taskIdWithDefault); + + testGroup = updateGroupWithParent(testGroup, groupService.getDefaultGroup().getStringId()); + + assert !authorizationService.canCallReassign(taskId); + assert authorizationService.canCallReassign(taskIdWithDefault); + + updateAssigneeOfTask(taskId, new ObjectId().toString()); + assert !authorizationService.canCallReassign(taskId); + + ProcessRole posProcessRole = processRoleRepository.findByImportId("pos_process_role"); + assignProcessRole(testGroup.getStringId(), posProcessRole); + assert authorizationService.canCallReassign(taskId); + + ProcessRole negProcessRole = processRoleRepository.findByImportId("neg_process_role"); + assignProcessRole(testGroup.getStringId(), negProcessRole); + assert !authorizationService.canCallReassign(taskId); + + CaseRole posCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_case_role"); + assignCaseRole(testGroup.getStringId(), posCaseRole); + assert authorizationService.canCallReassign(taskId); + + CaseRole negCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_case_role"); + assignCaseRole(testGroup.getStringId(), negCaseRole); + assert !authorizationService.canCallReassign(taskId); + + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + assignAppRole(testGroup.getStringId(), adminAppRole); + assert authorizationService.canCallReassign(taskId); + + TestHelper.logout(); + assert !authorizationService.canCallReassign(taskId); + } + + @Test + public void canCallFinish() { + // order of assertions is important! + assert !authorizationService.canCallFinish(null); + assert !authorizationService.canCallFinish("wrong id"); + + String taskId = testCase.getTaskStringId("t_finish"); + String taskIdWithDefault = testCaseWithDefault.getTaskStringId("t_finish"); + + assert !authorizationService.canCallFinish(taskId); + + updateAssigneeOfTask(taskIdWithDefault, sessionManagerService.getActiveActorId()); + assert authorizationService.canCallFinish(taskIdWithDefault); + + updateAssigneeOfTask(taskId, new ObjectId().toString()); + assert !authorizationService.canCallFinish(taskId); + + ProcessRole posProcessRole = processRoleRepository.findByImportId("pos_process_role"); + assignProcessRole(testIdentity.getMainActorId(), posProcessRole); + assert !authorizationService.canCallFinish(taskId); + + updateAssigneeOfTask(taskId, sessionManagerService.getActiveActorId()); + assert authorizationService.canCallFinish(taskId); + + ProcessRole negProcessRole = processRoleRepository.findByImportId("neg_process_role"); + assignProcessRole(testIdentity.getMainActorId(), negProcessRole); + assert !authorizationService.canCallFinish(taskId); + + CaseRole posCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_case_role"); + assignCaseRole(testIdentity.getMainActorId(), posCaseRole); + assert authorizationService.canCallFinish(taskId); + + CaseRole negCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_case_role"); + assignCaseRole(testIdentity.getMainActorId(), negCaseRole); + assert !authorizationService.canCallFinish(taskId); + + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + assignAppRole(testIdentity.getMainActorId(), adminAppRole); + assert authorizationService.canCallFinish(taskId); + + TestHelper.logout(); + assert !authorizationService.canCallFinish(taskId); + } + + @Test + public void canCallFinishByGroups() { + // order of assertions is important! + User testUser = initializeTestUserWithGroup(); + + assert !roleAssignmentRepository.findAllByActorId(testUser.getStringId()).iterator().hasNext(); + + assert !authorizationService.canCallFinish(null); + + String taskId = testCase.getTaskStringId("t_finish"); + String taskIdWithDefault = testCaseWithDefault.getTaskStringId("t_finish"); + + assert !authorizationService.canCallFinish(taskId); + updateAssigneeOfTask(taskIdWithDefault, sessionManagerService.getActiveActorId()); + assert !authorizationService.canCallFinish(taskIdWithDefault); + + testGroup = updateGroupWithParent(testGroup, groupService.getDefaultGroup().getStringId()); + + assert !authorizationService.canCallFinish(taskId); + assert authorizationService.canCallFinish(taskIdWithDefault); + + updateAssigneeOfTask(taskId, new ObjectId().toString()); + assert !authorizationService.canCallFinish(taskId); + + ProcessRole posProcessRole = processRoleRepository.findByImportId("pos_process_role"); + assignProcessRole(testGroup.getStringId(), posProcessRole); + assert !authorizationService.canCallFinish(taskId); + + updateAssigneeOfTask(taskId, sessionManagerService.getActiveActorId()); + assert authorizationService.canCallFinish(taskId); + + ProcessRole negProcessRole = processRoleRepository.findByImportId("neg_process_role"); + assignProcessRole(testGroup.getStringId(), negProcessRole); + assert !authorizationService.canCallFinish(taskId); + + CaseRole posCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_case_role"); + assignCaseRole(testGroup.getStringId(), posCaseRole); + assert authorizationService.canCallFinish(taskId); + + CaseRole negCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_case_role"); + assignCaseRole(testGroup.getStringId(), negCaseRole); + assert !authorizationService.canCallFinish(taskId); + + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + assignAppRole(testGroup.getStringId(), adminAppRole); + assert authorizationService.canCallFinish(taskId); + + TestHelper.logout(); + assert !authorizationService.canCallFinish(taskId); + } + + @Test + public void canCallSetData() { + // order of assertions is important! + assert !authorizationService.canCallSetData(null); + assert !authorizationService.canCallSetData("wrong id"); + + String taskId = testCase.getTaskStringId("t_setdata"); + + assert !authorizationService.canCallSetData(taskId); + + updateAssigneeOfTask(taskId, new ObjectId().toString()); + assert !authorizationService.canCallSetData(taskId); + + updateAssigneeOfTask(taskId, sessionManagerService.getActiveActorId()); + assert authorizationService.canCallSetData(taskId); + + updateAssigneeOfTask(taskId, new ObjectId().toString()); + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + assignAppRole(testIdentity.getMainActorId(), adminAppRole); + assert authorizationService.canCallSetData(taskId); + + updateAssigneeOfTask(taskId, sessionManagerService.getActiveActorId()); + TestHelper.logout(); + assert !authorizationService.canCallSetData(taskId); + } + + @Test + public void canCallSetDataByGroups() { + // order of assertions is important! + User testUser = initializeTestUserWithGroup(); + + assert !roleAssignmentRepository.findAllByActorId(testUser.getStringId()).iterator().hasNext(); + + assert !authorizationService.canCallSetData(null); + + String taskId = testCase.getTaskStringId("t_setdata"); + + assert !authorizationService.canCallSetData(taskId); + + updateAssigneeOfTask(taskId, new ObjectId().toString()); + assert !authorizationService.canCallSetData(taskId); + + updateAssigneeOfTask(taskId, sessionManagerService.getActiveActorId()); + assert authorizationService.canCallSetData(taskId); + + updateAssigneeOfTask(taskId, new ObjectId().toString()); + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + assignAppRole(testGroup.getStringId(), adminAppRole); + assert authorizationService.canCallSetData(taskId); + + updateAssigneeOfTask(taskId, sessionManagerService.getActiveActorId()); + TestHelper.logout(); + assert !authorizationService.canCallSetData(taskId); + } + + @Test + public void canCallGetData() { + // order of assertions is important! + assert !authorizationService.canCallGetData((String) null); + assert !authorizationService.canCallGetData("wrong id"); + assert !authorizationService.canCallGetData((Task) null); + + String taskId = testCase.getTaskStringId("t_getdata"); + Task task = taskService.findById(taskId); + String taskIdWithDefault = testCaseWithDefault.getTaskStringId("t_getdata"); + Task taskWithDefault = taskService.findById(taskIdWithDefault); + + assert !authorizationService.canCallGetData(taskId); + assert !authorizationService.canCallGetData(task); + + assert authorizationService.canCallGetData(taskIdWithDefault); + assert authorizationService.canCallGetData(taskWithDefault); + updateStateOfTask(taskIdWithDefault, State.DISABLED); + taskWithDefault = taskService.findById(taskIdWithDefault); + assert !authorizationService.canCallGetData(taskIdWithDefault); + assert !authorizationService.canCallGetData(taskWithDefault); + + ProcessRole posProcessRole = processRoleRepository.findByImportId("pos_process_role"); + assignProcessRole(testIdentity.getMainActorId(), posProcessRole); + assert authorizationService.canCallGetData(taskId); + assert authorizationService.canCallGetData(task); + + ProcessRole negProcessRole = processRoleRepository.findByImportId("neg_process_role"); + assignProcessRole(testIdentity.getMainActorId(), negProcessRole); + assert !authorizationService.canCallGetData(taskId); + assert !authorizationService.canCallGetData(task); + + CaseRole posCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_case_role"); + assignCaseRole(testIdentity.getMainActorId(), posCaseRole); + assert authorizationService.canCallGetData(taskId); + assert authorizationService.canCallGetData(task); + + CaseRole negCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_case_role"); + assignCaseRole(testIdentity.getMainActorId(), negCaseRole); + assert !authorizationService.canCallGetData(taskId); + assert !authorizationService.canCallGetData(task); + + updateStateOfTask(taskId, State.DISABLED); + task = taskService.findById(taskId); + + assert !authorizationService.canCallGetData(taskId); + assert !authorizationService.canCallGetData(task); + + posProcessRole = processRoleRepository.findByImportId("pos_getdata_disabled_process_role"); + assignProcessRole(testIdentity.getMainActorId(), posProcessRole); + assert authorizationService.canCallGetData(taskId); + assert authorizationService.canCallGetData(task); + + negProcessRole = processRoleRepository.findByImportId("neg_getdata_disabled_process_role"); + assignProcessRole(testIdentity.getMainActorId(), negProcessRole); + assert !authorizationService.canCallGetData(taskId); + assert !authorizationService.canCallGetData(task); + + posCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_getdata_disabled_case_role"); + assignCaseRole(testIdentity.getMainActorId(), posCaseRole); + assert authorizationService.canCallGetData(taskId); + assert authorizationService.canCallGetData(task); + + negCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_getdata_disabled_case_role"); + assignCaseRole(testIdentity.getMainActorId(), negCaseRole); + assert !authorizationService.canCallGetData(taskId); + assert !authorizationService.canCallGetData(task); + + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + assignAppRole(testIdentity.getMainActorId(), adminAppRole); + assert authorizationService.canCallGetData(taskId); + assert authorizationService.canCallGetData(task); + + TestHelper.logout(); + assert !authorizationService.canCallGetData(taskId); + assert !authorizationService.canCallGetData(task); + } + + @Test + public void canCallGetDataByGroups() { + // order of assertions is important! + User testUser = initializeTestUserWithGroup(); + assert !roleAssignmentRepository.findAllByActorId(testUser.getStringId()).iterator().hasNext(); + + assert !authorizationService.canCallGetData((String) null); + + String taskId = testCase.getTaskStringId("t_getdata"); + String taskIdWithDefault = testCaseWithDefault.getTaskStringId("t_getdata"); + + assert !authorizationService.canCallGetData(taskId); + assert !authorizationService.canCallGetData(taskIdWithDefault); + + testGroup = updateGroupWithParent(testGroup, groupService.getDefaultGroup().getStringId()); + + assert !authorizationService.canCallGetData(taskId); + assert authorizationService.canCallGetData(taskIdWithDefault); + + updateStateOfTask(taskIdWithDefault, State.DISABLED); + assert !authorizationService.canCallGetData(taskIdWithDefault); + + ProcessRole posProcessRole = processRoleRepository.findByImportId("pos_process_role"); + assignProcessRole(testGroup.getStringId(), posProcessRole); + assert authorizationService.canCallGetData(taskId); + + ProcessRole negProcessRole = processRoleRepository.findByImportId("neg_process_role"); + assignProcessRole(testGroup.getStringId(), negProcessRole); + assert !authorizationService.canCallGetData(taskId); + + CaseRole posCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_case_role"); + assignCaseRole(testGroup.getStringId(), posCaseRole); + assert authorizationService.canCallGetData(taskId); + + CaseRole negCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_case_role"); + assignCaseRole(testGroup.getStringId(), negCaseRole); + assert !authorizationService.canCallGetData(taskId); + + updateStateOfTask(taskId, State.DISABLED); + + assert !authorizationService.canCallGetData(taskId); + + posProcessRole = processRoleRepository.findByImportId("pos_getdata_disabled_process_role"); + assignProcessRole(testGroup.getStringId(), posProcessRole); + assert authorizationService.canCallGetData(taskId); + + negProcessRole = processRoleRepository.findByImportId("neg_getdata_disabled_process_role"); + assignProcessRole(testGroup.getStringId(), negProcessRole); + assert !authorizationService.canCallGetData(taskId); + + posCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_getdata_disabled_case_role"); + assignCaseRole(testGroup.getStringId(), posCaseRole); + assert authorizationService.canCallGetData(taskId); + + negCaseRole = caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_getdata_disabled_case_role"); + assignCaseRole(testGroup.getStringId(), negCaseRole); + assert !authorizationService.canCallGetData(taskId); + + ApplicationRole adminAppRole = applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE); + assignAppRole(testGroup.getStringId(), adminAppRole); + assert authorizationService.canCallGetData(taskId); + + TestHelper.logout(); + assert !authorizationService.canCallGetData(taskId); + } + + @Test + public void canCallGetDataDisabled() { + String taskId = testCaseWithDefault.getTaskStringId("t_getdata_disabled"); + + assert authorizationService.canCallGetData(taskId); + updateStateOfTask(taskId, State.ENABLED); + assert !authorizationService.canCallGetData(taskId); + } + + @Test + public void canCallGetDataDisabledByGroups() { + User testUser = initializeTestUserWithGroup(); + assert !roleAssignmentRepository.findAllByActorId(testUser.getStringId()).iterator().hasNext(); + + String taskId = testCaseWithDefault.getTaskStringId("t_getdata_disabled"); + + assert !authorizationService.canCallGetData(taskId); + testGroup = updateGroupWithParent(testGroup, groupService.getDefaultGroup().getStringId()); + assert authorizationService.canCallGetData(taskId); + + updateStateOfTask(taskId, State.ENABLED); + assert !authorizationService.canCallGetData(taskId); + } + + private void updateAssigneeOfTask(String taskId, String newAssigneeId) { + Task task = taskService.findOne(taskId); + task.setAssigneeId(newAssigneeId); + taskService.save(task); + } + + private void updateStateOfTask(String taskId, State newState) { + Task task = taskService.findOne(taskId); + task.setState(newState); + taskService.save(task); + } + + private void assignProcessRole(String actorId, ProcessRole role) { + RoleAssignment assignment = new ProcessRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(role.getStringId()); + roleAssignmentRepository.save(assignment); + } + + private void assignCaseRole(String actorId, CaseRole role) { + CaseRoleAssignment assignment = new CaseRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(role.getStringId()); + assignment.setCaseId(testCase.getStringId()); + roleAssignmentRepository.save(assignment); + } + + private void assignAppRole(String actorId, ApplicationRole role) { + ApplicationRoleAssignment assignment = new ApplicationRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(role.getStringId()); + roleAssignmentRepository.save(assignment); + } + + private Group updateGroupWithParent(Group group, String parentGroupId) { + return new Group(dataService.setData(new SetDataParams(group.getCase(), GroupParams.with() + .parentGroupId(CaseField.withValue(List.of(parentGroupId))) + .build() + .toDataSet(), null)).getCase()); + } + + private User updateUserMembership(User user, Set groupIds) { + return new User(dataService.setData(new SetDataParams(user.getCase(), UserParams.with() + .groupIds(CaseField.withValue(new ArrayList<>(groupIds))) + .build() + .toDataSet(), null)).getCase()); + } + + private User initializeTestUserWithGroup() { + Optional testUserOpt = userService.findById(testIdentity.getMainActorId()); + assert testUserOpt.isPresent(); + testGroup = createGroup("test group"); + return updateUserMembership(testUserOpt.get(), Set.of(testGroup.getStringId())); + } + + private Group createGroup(String name) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(GroupConstants.PROCESS_IDENTIFIER) + .title(name) + .build(); + Case groupCase = workflowService.createCase(createCaseParams).getCase(); + return new Group(dataService.setData(new SetDataParams(groupCase, GroupParams.with() + .name(new TextField(name)) + .build() + .toDataSet(), null)).getCase()); + } +} diff --git a/src/test/java/com/netgrif/application/engine/authorization/service/UserServiceTest.java b/src/test/java/com/netgrif/application/engine/authorization/service/UserServiceTest.java new file mode 100644 index 00000000000..9b5b1bf8531 --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/authorization/service/UserServiceTest.java @@ -0,0 +1,398 @@ +package com.netgrif.application.engine.authorization.service; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authentication.domain.constants.SystemUserConstants; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authorization.domain.Group; +import com.netgrif.application.engine.authorization.domain.User; +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.authorization.domain.constants.UserConstants; +import com.netgrif.application.engine.authorization.domain.params.GroupParams; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.startup.DefaultGroupRunner; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import com.netgrif.application.engine.workflow.service.throwable.CaseAlreadyExistsException; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import com.netgrif.application.engine.petrinet.domain.Process; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class UserServiceTest { + + @Autowired + private TestHelper testHelper; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private CaseRepository caseRepository; + + @Autowired + private IPetriNetService petriNetService; + + @Autowired + private IDataService dataService; + + @Autowired + private UserService userService; + + @Autowired + private DefaultGroupRunner defaultGroupRunner; + + @BeforeEach + void before() { + testHelper.truncateDbs(); + } + + @Test + void testFindByEmail() throws InterruptedException { + assert userService.findByEmail(null).isEmpty(); + assert userService.findByEmail("nonexisting@email.com").isEmpty(); + + String email = "some@email.com"; + createUser(email); + + Thread.sleep(2000); + assert userService.findByEmail(email).isPresent(); + } + + @Test + void testExistsByEmail() throws InterruptedException { + assert !userService.existsByEmail(null); + assert !userService.existsByEmail("nonexisting@email.com"); + + String email = "some@email.com"; + createUser(email); + + Thread.sleep(2000); + assert userService.existsByEmail(email); + } + + @Test + void testFindById() throws InterruptedException { + assert userService.findById(null).isEmpty(); + assert userService.findById(new ObjectId().toString()).isEmpty(); + + String email = "some@email.com"; + User user = createUser(email); + + Thread.sleep(2000); + assert userService.findById(user.getStringId()).isPresent(); + } + + @Test + void testExistsById() { + assert !userService.existsById(null); + assert !userService.existsById(new ObjectId().toString()); + + String email = "some@email.com"; + User user = createUser(email); + + assert userService.existsById(user.getStringId()); + } + + @Test + void testFindAll() { + Process userProcess = petriNetService.getNewestVersionByIdentifier(UserConstants.PROCESS_IDENTIFIER); + caseRepository.deleteAllByPetriNetObjectId(userProcess.getId()); + + assert userService.findAll().isEmpty(); + + createUser("some@email.com"); + createUser("some@email2.com"); + + assert userService.findAll().size() == 2; + } + + @Test + void getSystemUser() { + User systemUser = userService.getSystemUser(); + + assert systemUser != null; + assert systemUser.getEmail().equals(SystemUserConstants.EMAIL); + assert systemUser.getFirstname().equals(SystemUserConstants.FIRSTNAME); + assert systemUser.getLastname().equals(SystemUserConstants.LASTNAME); + assert systemUser.getEmail().equals(SystemUserConstants.EMAIL); + assert systemUser.getFullName().equals(String.join(" ", SystemUserConstants.FIRSTNAME, + SystemUserConstants.LASTNAME)); + assert ObjectId.isValid(systemUser.getStringId()); + } + + @Test + void testCreate() throws InterruptedException { + String email = "some@email.com"; + String firstname = "firstname"; + String lastname = "lastname"; + String propertyKey = "property"; + String propertyValue = "isActive"; + User user = userService.create(UserParams.with() + .email(new TextField(email)) + .firstname(new TextField(firstname)) + .lastname(new TextField(lastname)) + .properties(Map.of(propertyKey, propertyValue)) + .build()); + + assert user != null && user.getCase() != null; + assert user.getEmail().equals(email); + assert user.getFirstname().equals(firstname); + assert user.getLastname().equals(lastname); + assert user.getGroupIds() != null; + assert user.getGroupIds().size() == 1; + assert user.getGroupIds().get(0).equals(defaultGroupRunner.getDefaultGroup().getStringId()); + assert user.getCase().getProperties() != null; + assert user.getCase().getProperties().size() == 1; + assert user.getCase().getProperties().containsKey(propertyKey); + assert user.getCase().getProperties().get(propertyKey).equals(propertyValue); + + assertThrows(IllegalArgumentException.class, () -> userService.create(UserParams.with() + .firstname(new TextField(firstname)) + .lastname(new TextField(lastname)) + .build())); + + assertThrows(IllegalArgumentException.class, () -> userService.create(UserParams.with() + .email(new TextField(SystemUserConstants.EMAIL)) + .build())); + + assertThrows(IllegalArgumentException.class, () -> userService.create(GroupParams.with() + .name(new TextField("wrong type of parameters")) + .build())); + + assertThrows(IllegalArgumentException.class, () -> userService.create(null)); + + Thread.sleep(2000); + assertThrows(CaseAlreadyExistsException.class, () -> userService.create(UserParams.with() + .email(new TextField(email)) + .build())); + } + + @Test + void testUpdate() { + String email = "some@email.com"; + User user = createUser(email); + assert user.getEmail().equals(email); + assert user.getFirstname() == null; + assert user.getLastname() == null; + assert user.getGroupIds() != null; + assert user.getGroupIds().size() == 1; + assert user.getGroupIds().get(0).equals(defaultGroupRunner.getDefaultGroup().getStringId()); + assert user.getCase().getProperties() == null || user.getCase().getProperties().isEmpty(); + + assertThrows(IllegalArgumentException.class, () -> userService.update(user, UserParams.with() + .email(new TextField(null)) + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .build())); + + assertThrows(IllegalArgumentException.class, () -> userService.update(user, null)); + assertThrows(IllegalArgumentException.class, () -> userService.update(null, UserParams.with() + .email(new TextField("email")) + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .build())); + + String newFirstname = "newFirstname"; + String newLastname = "newLastname"; + String propertyKey = "property"; + String propertyValue = "isActive"; + Group testGroup = createGroup("test group"); + User updatedUser = userService.update(user, UserParams.with() + .email(new TextField(email)) + .firstname(new TextField(newFirstname)) + .lastname(new TextField(newLastname)) + .groupIds(CaseField.withValue(List.of(testGroup.getStringId()))) + .properties(Map.of(propertyKey, propertyValue)) + .build()); + + assert user.getStringId().equals(updatedUser.getStringId()); + assert updatedUser.getEmail().equals(email); + assert updatedUser.getFirstname().equals(newFirstname); + assert updatedUser.getLastname().equals(newLastname); + assert updatedUser.getGroupIds() != null; + assert updatedUser.getGroupIds().size() == 1; + assert updatedUser.getGroupIds().get(0).equals(testGroup.getStringId()); + assert updatedUser.getCase().getProperties() != null; + assert updatedUser.getCase().getProperties().size() == 1; + assert updatedUser.getCase().getProperties().containsKey(propertyKey); + assert updatedUser.getCase().getProperties().get(propertyKey).equals(propertyValue); + } + + @Test + void testAddGroup() { + Group group = createGroup("test group"); + User user = createUser("test@user.com"); + assert user.getGroupIds() != null; + assert user.getGroupIds().size() == 1; + + assertThrows(IllegalArgumentException.class, () -> userService.addGroup(null, group.getStringId())); + final User finalUser = user; + assertThrows(IllegalArgumentException.class, () -> userService.addGroup(finalUser, null)); + + user = userService.addGroup(user, group.getStringId()); + assert user.getGroupIds() != null; + assert user.getGroupIds().size() == 2; + assert user.getGroupIds().contains(defaultGroupRunner.getDefaultGroup().getStringId()); + assert user.getGroupIds().contains(group.getStringId()); + } + + @Test + void testAddGroups() { + Group group1 = createGroup("test group 1"); + Group group2 = createGroup("test group 2"); + User user = createUser("test@user.com"); + assert user.getGroupIds() != null; + assert user.getGroupIds().size() == 1; + + assertThrows(IllegalArgumentException.class, () -> userService.addGroups(null, Set.of(group1.getStringId(), + group2.getStringId()))); + final User finalUser = user; + assertThrows(IllegalArgumentException.class, () -> userService.addGroups(finalUser, null)); + + Set groupIdsToAdd = new HashSet<>(); + groupIdsToAdd.add(group1.getStringId()); + groupIdsToAdd.add(group2.getStringId()); + groupIdsToAdd.add(defaultGroupRunner.getDefaultGroup().getStringId()); + groupIdsToAdd.add(null); + + user = userService.addGroups(user, groupIdsToAdd); + assert user.getGroupIds() != null; + assert user.getGroupIds().size() == 3; + assert user.getGroupIds().contains(defaultGroupRunner.getDefaultGroup().getStringId()); + assert user.getGroupIds().contains(group1.getStringId()); + assert user.getGroupIds().contains(group2.getStringId()); + } + + @Test + void testRemoveGroup() { + Group group = createGroup("test group"); + User user = createUser("test@user.com", List.of(group.getStringId())); + assert user.getGroupIds() != null; + assert user.getGroupIds().size() == 2; + + assertThrows(IllegalArgumentException.class, () -> userService.removeGroup(null, group.getStringId())); + final User finalUser = user; + assertThrows(IllegalArgumentException.class, () -> userService.removeGroup(finalUser, null)); + + user = userService.removeGroup(user, group.getStringId()); + assert user.getGroupIds() != null; + assert user.getGroupIds().size() == 1; + assert user.getGroupIds().get(0).equals(defaultGroupRunner.getDefaultGroup().getStringId()); + + user = userService.removeGroup(user, defaultGroupRunner.getDefaultGroup().getStringId()); + assert user.getGroupIds() == null || user.getGroupIds().isEmpty(); + } + + @Test + void testRemoveGroups() { + Group group1 = createGroup("test group 1"); + Group group2 = createGroup("test group 2"); + User user = createUser("test@user.com", List.of(group1.getStringId(), group2.getStringId())); + assert user.getGroupIds() != null; + assert user.getGroupIds().size() == 3; + + assertThrows(IllegalArgumentException.class, () -> userService.removeGroups(null, Set.of(group1.getStringId()))); + final User finalUser = user; + assertThrows(IllegalArgumentException.class, () -> userService.removeGroups(finalUser, null)); + + Set groupIdsToRemove = new HashSet<>(Set.of(group1.getStringId(), group2.getStringId(), + defaultGroupRunner.getDefaultGroup().getStringId())); + groupIdsToRemove.add(null); + + user = userService.removeGroups(user, groupIdsToRemove); + assert user.getGroupIds() == null || user.getGroupIds().isEmpty(); + } + + @Test + void testForbiddenKeywords() { + assert !userService.registerForbiddenKeywords(null); + assert !userService.registerForbiddenKeywords(Set.of()); + + assert !userService.removeForbiddenKeywords(null); + assert !userService.removeForbiddenKeywords(Set.of()); + + Set keywords = Set.of("keyword1", "keyword2", "keyword3"); + assert !userService.removeForbiddenKeywords(keywords); + assert userService.registerForbiddenKeywords(keywords); + + assertThrows(IllegalArgumentException.class, () -> userService.create(UserParams.with() + .email(new TextField("keyword1")) + .build())); + + assertThrows(IllegalArgumentException.class, () -> userService.create(UserParams.with() + .email(new TextField("keyword2")) + .build())); + + assertThrows(IllegalArgumentException.class, () -> userService.create(UserParams.with() + .email(new TextField("keyword3")) + .build())); + + assert userService.removeForbiddenKeywords(Set.of("keyword1", "keyword2")); + + User user = userService.create(UserParams.with().email(new TextField("keyword1")).build()); + assert user != null; + + user = userService.create(UserParams.with().email(new TextField("keyword2")).build()); + assert user != null; + + assertThrows(IllegalArgumentException.class, () -> userService.create(UserParams.with() + .email(new TextField("keyword3")) + .build())); + + userService.clearForbiddenKeywords(); + + user = userService.create(UserParams.with().email(new TextField("keyword3")).build()); + assert user != null; + } + + private User createUser(String email) { + return createUser(email, new ArrayList<>()); + } + + private User createUser(String email, List additionalGroupIds) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(UserConstants.PROCESS_IDENTIFIER) + .title(email) + .build(); + Case userCase = workflowService.createCase(createCaseParams).getCase(); + List groupIds = new ArrayList<>(additionalGroupIds); + groupIds.add(defaultGroupRunner.getDefaultGroup().getStringId()); + return new User(dataService.setData(new SetDataParams(userCase, UserParams.with() + .email(new TextField(email)) + .groupIds(CaseField.withValue(groupIds)) + .build() + .toDataSet(), null)).getCase()); + } + + private Group createGroup(String name) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(GroupConstants.PROCESS_IDENTIFIER) + .title(name) + .build(); + Case groupCase = workflowService.createCase(createCaseParams).getCase(); + return new Group(dataService.setData(new SetDataParams(groupCase, GroupParams.with() + .name(new TextField(name)) + .build() + .toDataSet(), null)).getCase()); + } +} diff --git a/src/test/java/com/netgrif/application/engine/authorization/web/RBACControllerTest.java b/src/test/java/com/netgrif/application/engine/authorization/web/RBACControllerTest.java new file mode 100644 index 00000000000..49e09eb2873 --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/authorization/web/RBACControllerTest.java @@ -0,0 +1,13 @@ +package com.netgrif.application.engine.authorization.web; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class RBACControllerTest { + // todo: release/8.0.0 +} diff --git a/src/test/java/com/netgrif/application/engine/configuration/authentication/providers/NetgrifLdapAuthenticationProviderTest.java b/src/test/java/com/netgrif/application/engine/configuration/authentication/providers/NetgrifLdapAuthenticationProviderTest.java index 5f8ca432b04..e36010ec6ef 100644 --- a/src/test/java/com/netgrif/application/engine/configuration/authentication/providers/NetgrifLdapAuthenticationProviderTest.java +++ b/src/test/java/com/netgrif/application/engine/configuration/authentication/providers/NetgrifLdapAuthenticationProviderTest.java @@ -1,22 +1,20 @@ package com.netgrif.application.engine.configuration.authentication.providers; import com.netgrif.application.engine.TestHelper; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.User; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.service.interfaces.IIdentityService; +import com.netgrif.application.engine.authorization.domain.ProcessRole; import com.netgrif.application.engine.ldap.domain.LdapGroupRef; -import com.netgrif.application.engine.ldap.domain.LdapUser; import com.netgrif.application.engine.ldap.service.LdapUserService; import com.netgrif.application.engine.ldap.service.interfaces.ILdapGroupRefService; import com.netgrif.application.engine.orgstructure.web.requestbodies.LdapGroupRoleAssignRequestBody; import com.netgrif.application.engine.orgstructure.web.requestbodies.LdapGroupSearchBody; import com.netgrif.application.engine.orgstructure.web.responsebodies.LdapGroupResponseBody; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.VersionType; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.startup.SuperCreator; -import org.bson.types.ObjectId; -import org.json.JSONArray; import org.json.JSONObject; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -32,10 +30,7 @@ import org.springframework.web.context.WebApplicationContext; import java.io.FileInputStream; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; @@ -61,6 +56,10 @@ class NetgrifLdapAuthenticationProviderTest { @Autowired private IPetriNetService petriNetService; + + @Autowired + private IIdentityService identityService; + @Autowired private TestHelper testHelper; @@ -114,10 +113,9 @@ void getMyLDAPGroups() throws Exception { .andExpect(status().isOk()) .andReturn(); - IUser ldapUser = userService.findByEmail(USER_EMAIL_Test2); - assert ldapUser != null; - assert ldapUser instanceof LdapUser; - assert ((LdapUser) ldapUser).getMemberOf().size() == 2; + Optional identityOpt = identityService.findByUsername(USER_EMAIL_Test2); + assert identityOpt.isPresent(); +// assert ((LdapUser) identityOpt).getMemberOf().size() == 2; } @@ -130,15 +128,13 @@ void noLDAPGroups() throws Exception { .andExpect(status().isOk()) .andReturn(); - IUser ldapUser = userService.findByEmail(USER_EMAIL_Test3); - assert ldapUser != null; - assert ldapUser instanceof LdapUser; - assert ((LdapUser) ldapUser).getMemberOf().size() == 0; - + Optional identityOpt = identityService.findByUsername(USER_EMAIL_Test3); + assert identityOpt.isPresent(); +// assert ((LdapUser) identityOpt).getMemberOf().size() == 2; } @Test - void getMyProcessRole() throws Exception { + void getMyRole() throws Exception { MvcResult result = mvc.perform(get("/api/user/me") .with(httpBasic(USER_EMAIL_Test1, USER_PASSWORD_Test1)) .contentType(MediaType.APPLICATION_JSON) @@ -149,8 +145,9 @@ void getMyProcessRole() throws Exception { String string = result.getResponse().getContentAsString(); JSONObject json = new JSONObject(string); - JSONArray countProcessRole = (JSONArray) json.get("processRoles"); - assert countProcessRole.length() == 1; + // TODO: release/8.0.0 processRoles missing in json +// JSONArray countProcessRole = (JSONArray) json.get("processRoles"); +// assert countProcessRole.length() == 1; } @Test @@ -171,14 +168,17 @@ void searchGroups() { assert ldapGroupsTest.size() == 1; List ldapGroupsNothing = ldapGroupRefService.searchGroups("nothing"); - assert ldapGroupsNothing.size() == 0; + assert ldapGroupsNothing.isEmpty(); } @Test void assignRoleGroup() throws Exception { - PetriNet net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/role_all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet(); + Process net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/role_all_data.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess(); assert net != null; - Map roles = net.getRoles(); + // TODO: release/8.0.0 fix +// Map roles = net.getRoles(); + Map roles = null; assert roles != null; List ldapGroupsTest = ldapGroupRefService.searchGroups("test1"); @@ -191,8 +191,8 @@ void assignRoleGroup() throws Exception { ldapGroupRefService.setRoleToLdapGroup(ldapGroupsTest.get(0).getDn().toString(), role, superCreator.getLoggedSuper()); Set group = new HashSet<>(); group.add(ldapGroupsTest.get(0).getDn().toString()); - Set getRole = ldapGroupRefService.getProcessRoleByLdapGroup(group); - assert getRole.size() == roles.size(); + Set getProcessRole = ldapGroupRefService.getRoleByLdapGroup(group); + assert getProcessRole.size() == roles.size(); } @Test @@ -208,12 +208,16 @@ void assignRoleGroupAndCheck() throws Exception { String string = result.getResponse().getContentAsString(); JSONObject json = new JSONObject(string); - JSONArray countProcessRole = (JSONArray) json.get("processRoles"); - assert countProcessRole.length() == 1; + // TODO: release/8.0.0 processRoles missing in json +// JSONArray countProcessRole = (JSONArray) json.get("processRoles"); +// assert countProcessRole.length() == 1; - PetriNet net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/role_all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet(); + Process net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/role_all_data.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess(); assert net != null; - Map roles = net.getRoles(); + // TODO: release/8.0.0 fix +// Map roles = net.getRoles(); + Map roles = null; assert roles != null; List ldapGroupsTest = ldapGroupRefService.searchGroups("test1"); @@ -227,8 +231,8 @@ void assignRoleGroupAndCheck() throws Exception { Set group = new HashSet<>(); group.add(ldapGroupsTest.get(0).getDn().toString()); - Set getRole = ldapGroupRefService.getProcessRoleByLdapGroup(group); - assert getRole.size() == roles.size(); + Set getProcessRole = ldapGroupRefService.getRoleByLdapGroup(group); + assert getProcessRole.size() == roles.size(); MvcResult result2 = mvc.perform(get("/api/auth/login") @@ -241,8 +245,9 @@ void assignRoleGroupAndCheck() throws Exception { String response2 = result2.getResponse().getContentAsString(); JSONObject json2 = new JSONObject(response2); - JSONArray countProcessRole2 = (JSONArray) json2.get("processRoles"); - assert countProcessRole2.length() == 1 + roles.size(); + // TODO: release/8.0.0 processRoles missing in json +// JSONArray countProcessRole2 = (JSONArray) json2.get("processRoles"); +// assert countProcessRole2.length() == 1 + roles.size(); MvcResult result3 = mvc.perform(get("/api/auth/login") @@ -255,27 +260,26 @@ void assignRoleGroupAndCheck() throws Exception { String response3 = result3.getResponse().getContentAsString(); JSONObject json3 = new JSONObject(response3); - JSONArray countProcessRole3 = (JSONArray) json3.get("processRoles"); - assert countProcessRole3.length() == 1 + roles.size(); - - + // TODO: release/8.0.0 processRoles missing in json +// JSONArray countProcessRole3 = (JSONArray) json3.get("processRoles"); +// assert countProcessRole3.length() == 1 + roles.size(); } @Test - void getProcessRole() { + void getRole() { Set findDn = Set.of("nothing"); - Set processRoles = ldapGroupRefService.getProcessRoleByLdapGroup(findDn); - assert processRoles.size() == 0; + Set processRoles = ldapGroupRefService.getRoleByLdapGroup(findDn); + assert processRoles.isEmpty(); } @Test void LdapUserTest() { - LdapUser user = new LdapUser("dn", "commonName", "uid", "homeDirectory", "email", "name", "surname", null, "telNumber"); - assert user.getDn().equals("dn"); - assert user.getUid().equals("uid"); - assert user.getCommonName().equals("commonName"); - assert user.getHomeDirectory().equals("homeDirectory"); - assert user.getTelNumber().equals("telNumber"); +// LdapUser user = new LdapUser("dn", "commonName", "uid", "homeDirectory", "email", "name", "surname", null, "telNumber"); +// assert user.getDn().equals("dn"); +// assert user.getUid().equals("uid"); +// assert user.getCommonName().equals("commonName"); +// assert user.getHomeDirectory().equals("homeDirectory"); +// assert user.getTelNumber().equals("telNumber"); } @Test @@ -316,18 +320,17 @@ void LdapGroupRoleAssignRequestBodyTest() { @Test void createLdapUserTest() { - LdapUser user = new LdapUser(); - assert user != null; - User test = new User(); - user.loadFromUser(test); - assert user!= null; - LdapUser user2 = new LdapUser(new ObjectId()); - assert user2 != null; - assert user2.getStringId() != null; - LdapUser ldapUser = new LdapUser("dn", "commonName", "uid", "homeDirectory", "email", "name", "surname", null, "telNumber"); - assert ldapUser != null; - assert ldapUser.getDn().equals("dn"); - +// LdapUser user = new LdapUser(); +// assert user != null; +// User test = new User(); +// user.loadFromUser(test); +// assert user!= null; +// LdapUser user2 = new LdapUser(new ObjectId()); +// assert user2 != null; +// assert user2.getStringId() != null; +// LdapUser ldapUser = new LdapUser("dn", "commonName", "uid", "homeDirectory", "email", "name", "surname", null, "telNumber"); +// assert ldapUser != null; +// assert ldapUser.getDn().equals("dn"); } } diff --git a/src/test/java/com/netgrif/application/engine/elastic/ElasticCaseSearchPermissionTest.java b/src/test/java/com/netgrif/application/engine/elastic/ElasticCaseSearchPermissionTest.java new file mode 100644 index 00000000000..ead514bd841 --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/elastic/ElasticCaseSearchPermissionTest.java @@ -0,0 +1,319 @@ +package com.netgrif.application.engine.elastic; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authorization.domain.*; +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.authorization.domain.params.GroupParams; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.authorization.domain.repositories.CaseRoleRepository; +import com.netgrif.application.engine.authorization.domain.repositories.ProcessRoleRepository; +import com.netgrif.application.engine.authorization.domain.repositories.RoleAssignmentRepository; +import com.netgrif.application.engine.authorization.service.interfaces.IGroupService; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; +import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; +import com.netgrif.application.engine.petrinet.domain.VersionType; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; +import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; +import com.netgrif.application.engine.startup.ImportHelper; +import com.netgrif.application.engine.startup.SuperCreator; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import com.netgrif.application.engine.petrinet.domain.Process; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.*; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class ElasticCaseSearchPermissionTest { + + @Autowired + private IElasticCaseService elasticCaseService; + + @Autowired + private RoleAssignmentRepository roleAssignmentRepository; + + @Autowired + private ProcessRoleRepository processRoleRepository; + + @Autowired + private CaseRoleRepository caseRoleRepository; + + @Autowired + private ApplicationRoleRunner applicationRoleRunner; + + @Autowired + private IPetriNetService petriNetService; + + @Autowired + private ImportHelper importHelper; + + @Autowired + private TestHelper testHelper; + + @Autowired + private SuperCreator superCreator; + + @Autowired + private IUserService userService; + + @Autowired + private IGroupService groupService; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private IDataService dataService; + + private Identity testIdentity; + + private Group testGroup; + + private Case testCase; + + private CaseSearchRequest request; + + @BeforeEach + public void before() { + testHelper.truncateDbs(); + createIdentityWithActor(); + } + + /** + * todo javadoc + * */ + @Test + public void testViewPermissionsOrdered() throws InterruptedException, IOException, MissingPetriNetMetaDataException { + createTestCase("case_authorization_test"); + buildSearchRequest(); + Thread.sleep(2000); + + assertWithoutRole(); + String actorId = testIdentity.getMainActorId(); + assertWithAddedPosProcessRole(actorId); + assertWithAddedNegProcessRole(actorId); + assertWithAddedPosCaseRole(actorId); + assertWithAddedNegCaseRole(actorId); + assertWithAddedAdminAppRole(actorId); + } + + /** + * todo javadoc + * */ + @Test + public void testViewPermissionsByGroupsOrdered() throws InterruptedException, IOException, MissingPetriNetMetaDataException { + createTestCase("case_authorization_test"); + buildSearchRequest(); + initializeTestUserWithGroup(); + Thread.sleep(2000); + + assertWithoutRole(); + String actorId = testGroup.getStringId(); + assertWithAddedPosProcessRole(actorId); + assertWithAddedNegProcessRole(actorId); + assertWithAddedPosCaseRole(actorId); + assertWithAddedNegCaseRole(actorId); + assertWithAddedAdminAppRole(actorId); + } + + /** + * todo javadoc + * */ + @Test + public void testViewWithDefaultPermission() throws IOException, MissingPetriNetMetaDataException, InterruptedException { + createTestCase("case_authorization_default_test"); + buildSearchRequest(); + Thread.sleep(2000); + + Page pagedResult = doSearch(); + + assert pagedResult.hasContent(); + assert pagedResult.getTotalElements() == 1; + } + + /** + * todo javadoc + * */ + @Test + public void testViewWithDefaultPermissionByGroups() throws IOException, MissingPetriNetMetaDataException, InterruptedException { + createTestCase("case_authorization_default_test"); + buildSearchRequest(); + initializeTestUserWithGroup(); + Thread.sleep(2000); + + Page pagedResult = doSearch(); + assert !pagedResult.hasContent(); + + testGroup = updateGroupWithParent(testGroup, groupService.getDefaultGroup().getStringId()); + + pagedResult = doSearch(); + assert pagedResult.hasContent(); + assert pagedResult.getTotalElements() == 1; + } + + private void createIdentityWithActor() { + testIdentity = importHelper.createIdentity(IdentityParams.with() + .username(new TextField("username")) + .password(new TextField("password")) + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .build(), new ArrayList<>()); + } + + private void createTestCase(String identifier) throws IOException, MissingPetriNetMetaDataException { + Process process = petriNetService.importProcess(new ImportProcessParams(new FileInputStream(String.format("src/test/resources/petriNets/%s.xml", identifier)), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess(); + TestHelper.login(superCreator.getSuperIdentity()); + testCase = importHelper.createCase("Case permissions", process); + TestHelper.logout(); + } + + private void buildSearchRequest() { + request = new CaseSearchRequest(Map.of("stringId", List.of(testCase.getStringId()))); + } + + /** + * todo javadoc + * */ + private void assertWithoutRole() { + Page pagedResult = doSearch(); + assert !pagedResult.hasContent(); + } + + /** + * todo javadoc + * */ + private void assertWithAddedPosProcessRole(String actorId) { + assignProcessRole(actorId, processRoleRepository.findByImportId("pos_process_role")); + + Page pagedResult = doSearch(); + assert pagedResult.hasContent(); + assert pagedResult.getTotalElements() == 1; + } + + /** + * todo javadoc + * */ + private void assertWithAddedNegProcessRole(String actorId) { + assignProcessRole(actorId, processRoleRepository.findByImportId("neg_process_role")); + + Page pagedResult = doSearch(); + assert !pagedResult.hasContent(); + } + + /** + * todo javadoc + * */ + private void assertWithAddedPosCaseRole(String actorId) { + assignCaseRole(actorId, caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_case_role")); + + Page pagedResult = doSearch(); + assert pagedResult.hasContent(); + assert pagedResult.getTotalElements() == 1; + } + + /** + * todo javadoc + * */ + private void assertWithAddedNegCaseRole(String actorId) { + assignCaseRole(actorId, caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_case_role")); + + Page pagedResult = doSearch(); + assert !pagedResult.hasContent(); + } + + /** + * todo javadoc + * */ + private void assertWithAddedAdminAppRole(String actorId) { + assignAppRole(actorId, applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE)); + + Page pagedResult = doSearch(); + assert pagedResult.hasContent(); + assert pagedResult.getTotalElements() == 1; + } + + private Page doSearch() { + return elasticCaseService.search(List.of(request), testIdentity.toSession().getActiveActorId(), PageRequest.of(0, 2), + Locale.getDefault(), false); + } + + private Group updateGroupWithParent(Group group, String parentGroupId) { + return new Group(dataService.setData(new SetDataParams(group.getCase(), GroupParams.with() + .parentGroupId(CaseField.withValue(List.of(parentGroupId))) + .build() + .toDataSet(), null)).getCase()); + } + + private User updateUserMembership(User user, Set groupIds) { + return new User(dataService.setData(new SetDataParams(user.getCase(), UserParams.with() + .groupIds(CaseField.withValue(new ArrayList<>(groupIds))) + .build() + .toDataSet(), null)).getCase()); + } + + private User initializeTestUserWithGroup() { + Optional testUserOpt = userService.findById(testIdentity.getMainActorId()); + assert testUserOpt.isPresent(); + testGroup = createGroup("test group"); + return updateUserMembership(testUserOpt.get(), Set.of(testGroup.getStringId())); + } + + private Group createGroup(String name) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(GroupConstants.PROCESS_IDENTIFIER) + .title(name) + .build(); + Case groupCase = workflowService.createCase(createCaseParams).getCase(); + return new Group(dataService.setData(new SetDataParams(groupCase, GroupParams.with() + .name(new TextField(name)) + .build() + .toDataSet(), null)).getCase()); + } + + private void assignProcessRole(String actorId, ProcessRole role) { + RoleAssignment assignment = new ProcessRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(role.getStringId()); + roleAssignmentRepository.save(assignment); + } + + private void assignCaseRole(String actorId, CaseRole role) { + CaseRoleAssignment assignment = new CaseRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(role.getStringId()); + assignment.setCaseId(testCase.getStringId()); + roleAssignmentRepository.save(assignment); + } + + private void assignAppRole(String actorId, ApplicationRole role) { + ApplicationRoleAssignment assignment = new ApplicationRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(role.getStringId()); + roleAssignmentRepository.save(assignment); + } + + +} diff --git a/src/test/java/com/netgrif/application/engine/elastic/ElasticTaskSearchPermissionTest.java b/src/test/java/com/netgrif/application/engine/elastic/ElasticTaskSearchPermissionTest.java new file mode 100644 index 00000000000..4a82cf44b1f --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/elastic/ElasticTaskSearchPermissionTest.java @@ -0,0 +1,323 @@ +package com.netgrif.application.engine.elastic; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authorization.domain.*; +import com.netgrif.application.engine.authorization.domain.constants.GroupConstants; +import com.netgrif.application.engine.authorization.domain.params.GroupParams; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.authorization.domain.repositories.CaseRoleRepository; +import com.netgrif.application.engine.authorization.domain.repositories.ProcessRoleRepository; +import com.netgrif.application.engine.authorization.domain.repositories.RoleAssignmentRepository; +import com.netgrif.application.engine.authorization.service.interfaces.IGroupService; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; +import com.netgrif.application.engine.elastic.web.requestbodies.ElasticTaskSearchRequest; +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.petrinet.domain.VersionType; +import com.netgrif.application.engine.petrinet.domain.dataset.CaseField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; +import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.startup.ApplicationRoleRunner; +import com.netgrif.application.engine.startup.ImportHelper; +import com.netgrif.application.engine.startup.SuperCreator; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.Task; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.SetDataParams; +import com.netgrif.application.engine.workflow.service.interfaces.IDataService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.*; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class ElasticTaskSearchPermissionTest { + + @Autowired + private IElasticTaskService elasticTaskService; + + @Autowired + private IPetriNetService petriNetService; + + @Autowired + private RoleAssignmentRepository roleAssignmentRepository; + + @Autowired + private ProcessRoleRepository processRoleRepository; + + @Autowired + private CaseRoleRepository caseRoleRepository; + + @Autowired + private ApplicationRoleRunner applicationRoleRunner; + + @Autowired + private SuperCreator superCreator; + + @Autowired + private TestHelper testHelper; + + @Autowired + private ImportHelper importHelper; + + @Autowired + private IUserService userService; + + @Autowired + private IGroupService groupService; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private IDataService dataService; + + private Identity testIdentity; + + private Group testGroup; + + private Case testCase; + + private ElasticTaskSearchRequest request; + + @BeforeEach + public void before() { + testHelper.truncateDbs(); + createIdentityWithActor(); + } + + private void createIdentityWithActor() { + testIdentity = importHelper.createIdentity(IdentityParams.with() + .username(new TextField("username")) + .password(new TextField("password")) + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .build(), new ArrayList<>()); + } + + @Test + public void testViewPermissionsOrdered() throws InterruptedException, IOException, MissingPetriNetMetaDataException { + testCase = createTestCase("task_authorization_test"); + buildSearchRequest(testCase, "t_getdata"); + Thread.sleep(2000); + + assertWithoutRole(); + String actorId = testIdentity.getMainActorId(); + assertWithAddedPosProcessRole(actorId); + assertWithAddedNegProcessRole(actorId); + assertWithAddedPosCaseRole(actorId); + assertWithAddedNegCaseRole(actorId); + assertWithAddedAdminAppRole(actorId); + } + + @Test + public void testViewPermissionsByGroupsOrdered() throws InterruptedException, IOException, MissingPetriNetMetaDataException { + testCase = createTestCase("task_authorization_test"); + buildSearchRequest(testCase, "t_getdata"); + initializeTestUserWithGroup(); + Thread.sleep(2000); + + assertWithoutRole(); + String actorId = testGroup.getStringId(); + assertWithAddedPosProcessRole(actorId); + assertWithAddedNegProcessRole(actorId); + assertWithAddedPosCaseRole(actorId); + assertWithAddedNegCaseRole(actorId); + assertWithAddedAdminAppRole(actorId); + } + + @Test + public void testViewWithDefaultPermission() throws IOException, MissingPetriNetMetaDataException, InterruptedException { + Case testCaseWithDefault = createTestCase("task_authorization_default_test"); + Thread.sleep(2000); + + String transId = "t_getdata"; + buildSearchRequest(testCaseWithDefault, transId); + Page pagedResult = doSearch(); + assert pagedResult.hasContent(); + assert pagedResult.getTotalElements() == 1; + assert pagedResult.getContent().get(0).getTransitionId().equals(transId); + + transId = "t_getdata_disabled"; + buildSearchRequest(testCaseWithDefault, transId); + pagedResult = doSearch(); + assert pagedResult.hasContent(); + assert pagedResult.getTotalElements() == 1; + assert pagedResult.getContent().get(0).getTransitionId().equals(transId); + } + + @Test + public void testViewWithDefaultPermissionByGroups() throws IOException, MissingPetriNetMetaDataException, InterruptedException { + Case testCaseWithDefault = createTestCase("task_authorization_default_test"); + initializeTestUserWithGroup(); + Thread.sleep(2000); + + String transId = "t_getdata"; + buildSearchRequest(testCaseWithDefault, transId); + Page pagedResult = doSearch(); + assert !pagedResult.hasContent(); + + testGroup = updateGroupWithParent(testGroup, groupService.getDefaultGroup().getStringId()); + pagedResult = doSearch(); + + assert pagedResult.hasContent(); + assert pagedResult.getTotalElements() == 1; + assert pagedResult.getContent().get(0).getTransitionId().equals(transId); + + transId = "t_getdata_disabled"; + buildSearchRequest(testCaseWithDefault, transId); + pagedResult = doSearch(); + assert pagedResult.hasContent(); + assert pagedResult.getTotalElements() == 1; + assert pagedResult.getContent().get(0).getTransitionId().equals(transId); + } + + /** + * todo javadoc + * */ + private void assertWithoutRole() { + Page pagedResult = doSearch(); + assert !pagedResult.hasContent(); + } + + /** + * todo javadoc + * */ + private void assertWithAddedPosProcessRole(String actorId) { + assignProcessRole(actorId, processRoleRepository.findByImportId("pos_process_role")); + + Page pagedResult = doSearch(); + assert pagedResult.hasContent(); + assert pagedResult.getTotalElements() == 1; + } + + /** + * todo javadoc + * */ + private void assertWithAddedNegProcessRole(String actorId) { + assignProcessRole(actorId, processRoleRepository.findByImportId("neg_process_role")); + + Page pagedResult = doSearch(); + assert !pagedResult.hasContent(); + } + + /** + * todo javadoc + * */ + private void assertWithAddedPosCaseRole(String actorId) { + assignCaseRole(actorId, caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "pos_case_role")); + + Page pagedResult = doSearch(); + assert pagedResult.hasContent(); + assert pagedResult.getTotalElements() == 1; + } + + /** + * todo javadoc + * */ + private void assertWithAddedNegCaseRole(String actorId) { + assignCaseRole(actorId, caseRoleRepository.findByCaseIdAndImportId(testCase.getStringId(), "neg_case_role")); + + Page pagedResult = doSearch(); + assert !pagedResult.hasContent(); + } + + /** + * todo javadoc + * */ + private void assertWithAddedAdminAppRole(String actorId) { + assignAppRole(actorId, applicationRoleRunner.getAppRole(ApplicationRoleRunner.ADMIN_APP_ROLE)); + + Page pagedResult = doSearch(); + assert pagedResult.hasContent(); + assert pagedResult.getTotalElements() == 1; + } + + private Case createTestCase(String identifier) throws IOException, MissingPetriNetMetaDataException { + Process process = petriNetService.importProcess(new ImportProcessParams(new FileInputStream(String.format("src/test/resources/petriNets/%s.xml", identifier)), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess(); + TestHelper.login(superCreator.getSuperIdentity()); + Case testCase = importHelper.createCase("Task permissions", process); + TestHelper.logout(); + return testCase; + } + private void buildSearchRequest(Case testCase, String transitionId) { + request = new ElasticTaskSearchRequest(String.format("stringId:%s", testCase.getTaskStringId(transitionId))); + } + + private Page doSearch() { + return elasticTaskService.search(List.of(request), testIdentity.toSession().getActiveActorId(), PageRequest.of(0, 2), + Locale.getDefault(), false); + } + + private Group updateGroupWithParent(Group group, String parentGroupId) { + return new Group(dataService.setData(new SetDataParams(group.getCase(), GroupParams.with() + .parentGroupId(CaseField.withValue(List.of(parentGroupId))) + .build() + .toDataSet(), null)).getCase()); + } + + private User updateUserMembership(User user, Set groupIds) { + return new User(dataService.setData(new SetDataParams(user.getCase(), UserParams.with() + .groupIds(CaseField.withValue(new ArrayList<>(groupIds))) + .build() + .toDataSet(), null)).getCase()); + } + + private User initializeTestUserWithGroup() { + Optional testUserOpt = userService.findById(testIdentity.getMainActorId()); + assert testUserOpt.isPresent(); + testGroup = createGroup("test group"); + return updateUserMembership(testUserOpt.get(), Set.of(testGroup.getStringId())); + } + + private Group createGroup(String name) { + CreateCaseParams createCaseParams = CreateCaseParams.with() + .processIdentifier(GroupConstants.PROCESS_IDENTIFIER) + .title(name) + .build(); + Case groupCase = workflowService.createCase(createCaseParams).getCase(); + return new Group(dataService.setData(new SetDataParams(groupCase, GroupParams.with() + .name(new TextField(name)) + .build() + .toDataSet(), null)).getCase()); + } + + private void assignProcessRole(String actorId, ProcessRole role) { + RoleAssignment assignment = new ProcessRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(role.getStringId()); + roleAssignmentRepository.save(assignment); + } + + private void assignCaseRole(String actorId, CaseRole role) { + CaseRoleAssignment assignment = new CaseRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(role.getStringId()); + assignment.setCaseId(testCase.getStringId()); + roleAssignmentRepository.save(assignment); + } + + private void assignAppRole(String actorId, ApplicationRole role) { + ApplicationRoleAssignment assignment = new ApplicationRoleAssignment(); + assignment.setActorId(actorId); + assignment.setRoleId(role.getStringId()); + roleAssignmentRepository.save(assignment); + } +} diff --git a/src/test/java/com/netgrif/application/engine/importer/ConstructorAndDestructorTest.java b/src/test/java/com/netgrif/application/engine/importer/ConstructorAndDestructorTest.java index 51cf5337193..60a6db2504b 100644 --- a/src/test/java/com/netgrif/application/engine/importer/ConstructorAndDestructorTest.java +++ b/src/test/java/com/netgrif/application/engine/importer/ConstructorAndDestructorTest.java @@ -3,12 +3,13 @@ import com.netgrif.application.engine.TestHelper; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; import com.netgrif.application.engine.petrinet.domain.VersionType; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.startup.SuperCreator; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.QCase; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -46,9 +47,11 @@ public void before() { @Test public void testConstructorAndDestructor() throws MissingPetriNetMetaDataException, IOException, MissingIconKeyException { - ImportPetriNetEventOutcome outcome = petriNetService.importPetriNet(new FileInputStream("src/test/resources/constructor_destructor.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); + TestHelper.login(superCreator.getSuperIdentity()); + ImportPetriNetEventOutcome outcome = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/constructor_destructor.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())); - assert outcome.getNet() != null; + assert outcome.getProcess() != null; Optional caseOpt = caseRepository.findOne(QCase.case$.title.eq("Construct")); assert caseOpt.isPresent(); diff --git a/src/test/java/com/netgrif/application/engine/importer/ImporterTest.java b/src/test/java/com/netgrif/application/engine/importer/ImporterTest.java index 8a360a5225e..ad8f23fc8cb 100644 --- a/src/test/java/com/netgrif/application/engine/importer/ImporterTest.java +++ b/src/test/java/com/netgrif/application/engine/importer/ImporterTest.java @@ -1,43 +1,32 @@ package com.netgrif.application.engine.importer; +import com.netgrif.application.engine.EngineTest; import com.netgrif.application.engine.TestHelper; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.importer.service.AllDataConfiguration; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.VersionType; -import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.startup.SuperCreator; import com.netgrif.application.engine.utils.FullPageRequest; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; -import org.junit.jupiter.api.BeforeEach; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.Page; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; @SpringBootTest @ActiveProfiles({"test"}) @ExtendWith(SpringExtension.class) -public class ImporterTest { +public class ImporterTest extends EngineTest { - private static final String NET_ID = "prikladFM_test.xml"; + private static final String NET_ID = "prikladFM_test"; private static final String NET_TITLE = "Test"; private static final String NET_INITIALS = "TST"; private static final Integer NET_PLACES = 17; @@ -45,108 +34,54 @@ public class ImporterTest { private static final Integer NET_ARCS = 21; private static final Integer NET_FIELDS = 27; private static final Integer NET_ROLES = 3; - @Autowired - private TestHelper testHelper; - @Autowired - private PetriNetRepository repository; - @Autowired - private IWorkflowService workflowService; - @Autowired - private IPetriNetService petriNetService; - @Autowired - private SuperCreator superCreator; - @Autowired - private AllDataConfiguration allDataConfiguration; - - @BeforeEach - public void before() { - testHelper.truncateDbs(); - } @Test public void importPetriNet() throws MissingPetriNetMetaDataException, IOException, MissingIconKeyException { - petriNetService.importPetriNet(new FileInputStream("src/test/resources/prikladFM_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); + petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/prikladFM_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())); assertNetProperlyImported(); } @Test public void priorityTest() throws MissingPetriNetMetaDataException, IOException, MissingIconKeyException { - ImportPetriNetEventOutcome outcome = petriNetService.importPetriNet(new FileInputStream("src/test/resources/priority_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - assert outcome.getNet() != null; - - CreateCaseEventOutcome caseOutcome = workflowService.createCase(outcome.getNet().getStringId(), outcome.getNet().getTitle().getDefaultValue(), "color", superCreator.getLoggedSuper()); + ImportPetriNetEventOutcome outcome = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/priority_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())); + assert outcome.getProcess() != null; + + TestHelper.login(superCreator.getSuperIdentity()); + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(outcome.getProcess()) + .title(outcome.getProcess().getTitle().getDefaultValue()) + .authorId(superCreator.getLoggedSuper().getActiveActorId()) + .build(); + CreateCaseEventOutcome caseOutcome = workflowService.createCase(createCaseParams); assert caseOutcome.getCase() != null; } @Test public void dataGroupTest() throws MissingPetriNetMetaDataException, IOException, MissingIconKeyException { - ImportPetriNetEventOutcome outcome = petriNetService.importPetriNet(new FileInputStream("src/test/resources/datagroup_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); + ImportPetriNetEventOutcome outcome = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/datagroup_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())); - assert outcome.getNet() != null; + assert outcome.getProcess() != null; } @Test public void readArcImportTest() throws MissingPetriNetMetaDataException, IOException, MissingIconKeyException { - petriNetService.importPetriNet(new FileInputStream("src/test/resources/read_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - } - - @Test - public void externalMappingTest() throws MissingPetriNetMetaDataException, IOException, MissingIconKeyException { - ImportPetriNetEventOutcome outcome = petriNetService.importPetriNet(new FileInputStream("src/test/resources/mapping_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - - assertExternalMappingImport(outcome.getNet()); - } - - @Test - void importInvalidDataRefLayoutTest() throws FileNotFoundException { - LoggedUser loggedUser = superCreator.getLoggedSuper(); - assert loggedUser != null; - - FileInputStream fileInputStream = new FileInputStream("src/test/resources/invalid_data_ref_layout.xml"); - - assertThatThrownBy(() -> petriNetService.importPetriNet(fileInputStream, VersionType.MAJOR, loggedUser)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("doesn't have a layout"); - } - - private void assertExternalMappingImport(PetriNet imported) { - assert imported != null; - - String[] noDataTransitions = {"2", "3", "4", "36", "49"}; - - assert imported.getPlaces().size() == 11; - assert imported.getTransitions().size() == 12; - assert imported.getArcs().values().stream() - .mapToLong(List::size) - .sum() == 34; - assert imported.getDataSet().size() == 14; - assert imported.getRoles().size() == 2; - - imported.getTransitions().values().forEach(transition -> { - if (allDataConfiguration.getAllData().getId().equals(transition.getImportId())) { - return; - } - assert !transition.getRoles().isEmpty(); - if (Arrays.stream(noDataTransitions).anyMatch(x -> x.equals(transition.getImportId()))) { - assert transition.getDataSet().isEmpty(); - } else { - assert !transition.getDataSet().isEmpty(); - } - }); + petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/read_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())); } private void assertNetProperlyImported() { - assert repository.count() > 0; - Page nets = repository.findByIdentifier(NET_ID, new FullPageRequest()); - PetriNet net = nets.getContent().get(0); -// TODO: release/8.0.0 assertion error + assert processRepository.count() > 0; + Page nets = processRepository.findByIdentifier(NET_ID, new FullPageRequest()); + Process net = nets.getContent().get(0); assert net.getTitle().getDefaultValue().equals(NET_TITLE); - assert net.getInitials().equals(NET_INITIALS); + assert net.getProperties().get("initials").equals(NET_INITIALS); assert net.getPlaces().size() == NET_PLACES; assert net.getTransitions().size() == NET_TRANSITIONS; assert net.getArcs().size() == NET_ARCS; assert net.getDataSet().size() == NET_FIELDS; - assert net.getRoles().size() == NET_ROLES; } } diff --git a/src/test/java/com/netgrif/application/engine/manager/SessionManagerServiceTest.java b/src/test/java/com/netgrif/application/engine/manager/SessionManagerServiceTest.java index bdfb7ffd4c2..7a0c4886918 100644 --- a/src/test/java/com/netgrif/application/engine/manager/SessionManagerServiceTest.java +++ b/src/test/java/com/netgrif/application/engine/manager/SessionManagerServiceTest.java @@ -1,12 +1,15 @@ package com.netgrif.application.engine.manager; import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; import com.netgrif.application.engine.manager.service.interfaces.ISessionManagerService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -28,8 +31,50 @@ public void before() { } @Test - void getAllLoggedUsersTest() { - assert managerService.getAllLoggedUsers() != null; + void getLoggedIdentity() { + assert managerService.getLoggedIdentity() == null; + + LoggedIdentity loggedIdentity = login(); + + LoggedIdentity receivedLoggedIdentity = managerService.getLoggedIdentity(); + assert receivedLoggedIdentity != null; + assert receivedLoggedIdentity.getUsername().equals(loggedIdentity.getUsername()); + assert receivedLoggedIdentity.getPassword().equals(loggedIdentity.getPassword()); + assert receivedLoggedIdentity.getFullName().equals(loggedIdentity.getFullName()); + assert receivedLoggedIdentity.getIdentityId().equals(loggedIdentity.getIdentityId()); + assert receivedLoggedIdentity.getActiveActorId().equals(loggedIdentity.getActiveActorId()); + } + + @Test + void getActiveActorId() { + assert managerService.getActiveActorId() == null; + + LoggedIdentity loggedIdentity = login(); + + assert managerService.getActiveActorId().equals(loggedIdentity.getActiveActorId()); + } + + + + private LoggedIdentity login() { + LoggedIdentity loggedIdentity = LoggedIdentity.with() + .username("username") + .password("password") + .fullName("fullName") + .identityId("identityId") + .activeActorId("activeActorId") + .build(); + + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loggedIdentity, + loggedIdentity.getPassword(), loggedIdentity.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(token); + + return loggedIdentity; + } + + @Test + void getAllLoggedIdentitiesTest() { + assert managerService.getAllLoggedIdentities() != null; } @Test diff --git a/src/test/java/com/netgrif/application/engine/manager/responseclass/ResponseTest.java b/src/test/java/com/netgrif/application/engine/manager/responseclass/ResponseTest.java index 4fbfccf17a9..d883b70548e 100644 --- a/src/test/java/com/netgrif/application/engine/manager/responseclass/ResponseTest.java +++ b/src/test/java/com/netgrif/application/engine/manager/responseclass/ResponseTest.java @@ -1,8 +1,9 @@ package com.netgrif.application.engine.manager.responseclass; import com.netgrif.application.engine.TestHelper; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.manager.web.body.response.AllLoggedUsersResponse; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.manager.web.body.response.AllLoggedIdentitiesResponse; import com.netgrif.application.engine.manager.web.body.response.MessageLogoutResponse; import com.netgrif.application.engine.startup.SuperCreator; import org.junit.jupiter.api.BeforeEach; @@ -33,10 +34,10 @@ public void before() { } @Test - void allLoggedUsersResponseTest() { - Collection content = new ArrayList<>(); + void allLoggedIdentitiesResponseTest() { + Collection content = new ArrayList<>(); content.add(superCreator.getLoggedSuper()); - AllLoggedUsersResponse response = new AllLoggedUsersResponse(content); + AllLoggedIdentitiesResponse response = new AllLoggedIdentitiesResponse(content); assert response != null; assert response.getContent().size() == 1; } diff --git a/src/test/java/com/netgrif/application/engine/petrinet/service/ProcessRoleServiceTest.java b/src/test/java/com/netgrif/application/engine/petrinet/service/ProcessRoleServiceTest.java index ab62d721947..a509611b056 100644 --- a/src/test/java/com/netgrif/application/engine/petrinet/service/ProcessRoleServiceTest.java +++ b/src/test/java/com/netgrif/application/engine/petrinet/service/ProcessRoleServiceTest.java @@ -1,13 +1,14 @@ package com.netgrif.application.engine.petrinet.service; import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authorization.domain.ProcessRole; +import com.netgrif.application.engine.authorization.domain.Role; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; import com.netgrif.application.engine.petrinet.domain.VersionType; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; import com.netgrif.application.engine.startup.SuperCreator; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -19,7 +20,6 @@ import java.io.FileInputStream; import java.io.IOException; import java.util.List; -import java.util.Set; import static org.junit.jupiter.api.Assertions.*; @@ -39,7 +39,7 @@ class ProcessRoleServiceTest { private IPetriNetService petriNetService; @Autowired - private IProcessRoleService processRoleService; + private IRoleService roleService; @Autowired private SuperCreator superCreator; @@ -51,61 +51,53 @@ public void before() { @Test - void shouldFindAllProcessRoles() throws IOException, MissingPetriNetMetaDataException { - List roles = processRoleService.findAll(); - int originalRoles = roles.size(); - petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - petriNetService.importPetriNet(new FileInputStream("src/test/resources/role_all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - roles = processRoleService.findAll(); - assertNotNull(roles); - assertFalse(roles.isEmpty()); - assertEquals(originalRoles + 3, roles.size()); // + 2 roles from all_data and 1 role from role_all_data - } - - @Test - void shouldFindAllProcessRolesByPetriNet() throws IOException, MissingPetriNetMetaDataException { - ImportPetriNetEventOutcome eventOutcome = petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - List roles = processRoleService.findAll(eventOutcome.getNet().getStringId()); - assertNotNull(roles); - assertFalse(roles.isEmpty()); - assertEquals(2, roles.size()); - assertTrue(roles.stream().anyMatch(role -> ROLE_IMPORT_ID.equals(role.getImportId()))); - assertTrue(roles.stream().anyMatch(role -> ROLE_IMPORT_ID2.equals(role.getImportId()))); + void shouldFindAllRoles() throws IOException, MissingPetriNetMetaDataException { + List processRoles = roleService.findAll(); + int originalRoles = processRoles.size(); + petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, + superCreator.getLoggedSuper().getActiveActorId())); + petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/role_all_data.xml"), VersionType.MAJOR, + superCreator.getLoggedSuper().getActiveActorId())); + processRoles = roleService.findAll(); + assertNotNull(processRoles); + assertFalse(processRoles.isEmpty()); + assertEquals(originalRoles + 3, processRoles.size()); // + 2 roles from all_data and 1 role from role_all_data } @Test void shouldGetDefaultRole() { - ProcessRole role = processRoleService.defaultRole(); - assertNotNull(role); - assertEquals(ProcessRole.DEFAULT_ROLE, role.getImportId()); - assertEquals(ProcessRole.DEFAULT_ROLE, role.getName().getDefaultValue()); + Role processRole = roleService.findDefaultRole(); + assertNotNull(processRole); + assertEquals(ProcessRole.DEFAULT_ROLE, processRole.getImportId()); + assertEquals(ProcessRole.DEFAULT_ROLE, processRole.getTitleAsString()); } @Test void shouldGetAnonymousRole() { - ProcessRole role = processRoleService.anonymousRole(); - assertNotNull(role); - assertEquals(ProcessRole.ANONYMOUS_ROLE, role.getName().getDefaultValue()); - assertEquals(ProcessRole.ANONYMOUS_ROLE, role.getImportId()); + Role processRole = roleService.findAnonymousRole(); + assertNotNull(processRole); + assertEquals(ProcessRole.ANONYMOUS_ROLE, processRole.getTitleAsString()); + assertEquals(ProcessRole.ANONYMOUS_ROLE, processRole.getImportId()); } - @Test - void shouldFindAllProcessRolesByImportId() throws IOException, MissingPetriNetMetaDataException { - petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - Set roles = processRoleService.findAllByImportId(ROLE_IMPORT_ID); - assertNotNull(roles); - assertFalse(roles.isEmpty()); - assertEquals(1, roles.size()); - assertEquals(ROLE_IMPORT_ID, roles.stream().findFirst().get().getImportId()); - } +// @Test +// void shouldFindAllRolesByImportId() throws IOException, MissingPetriNetMetaDataException { +// petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId()); +// Set processRoles = roleService.findAllByImportId(ROLE_IMPORT_ID); +// assertNotNull(processRoles); +// assertFalse(processRoles.isEmpty()); +// assertEquals(1, processRoles.size()); +// assertEquals(ROLE_IMPORT_ID, processRoles.stream().findFirst().get().getImportId()); +// } @Test - void shouldFindAllProcessRolesByName() throws IOException, MissingPetriNetMetaDataException { - petriNetService.importPetriNet(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - Set roles = processRoleService.findAllByDefaultName("Process role"); - assertNotNull(roles); - assertFalse(roles.isEmpty()); - assertEquals(1, roles.size()); - assertEquals(ROLE_IMPORT_ID, roles.stream().findFirst().get().getImportId()); + void shouldFindAllRolesByName() throws IOException, MissingPetriNetMetaDataException { + petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/all_data.xml"), VersionType.MAJOR, + superCreator.getLoggedSuper().getActiveActorId())); + List processRoles = roleService.findProcessRolesByDefaultTitle("Process role"); + assertNotNull(processRoles); + assertFalse(processRoles.isEmpty()); + assertEquals(1, processRoles.size()); + assertEquals(ROLE_IMPORT_ID, processRoles.stream().findFirst().get().getImportId()); } } diff --git a/src/test/java/com/netgrif/application/engine/rules/service/RuleEngineTest.java b/src/test/java/com/netgrif/application/engine/rules/service/RuleEngineTest.java index 6bf60668eaf..1595d04f729 100644 --- a/src/test/java/com/netgrif/application/engine/rules/service/RuleEngineTest.java +++ b/src/test/java/com/netgrif/application/engine/rules/service/RuleEngineTest.java @@ -1,13 +1,10 @@ package com.netgrif.application.engine.rules.service; import com.netgrif.application.engine.TestHelper; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.configuration.drools.RefreshableKieBase; -import com.netgrif.application.engine.importer.model.EventType; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; import com.netgrif.application.engine.petrinet.domain.VersionType; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; @@ -15,10 +12,13 @@ import com.netgrif.application.engine.rules.domain.RuleRepository; import com.netgrif.application.engine.rules.domain.StoredRule; import com.netgrif.application.engine.rules.domain.facts.*; +import com.netgrif.application.engine.startup.SuperCreator; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.TaskParams; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import lombok.extern.slf4j.Slf4j; @@ -48,7 +48,7 @@ class RuleEngineTest { public static final String TEXT_VALUE = "new text value"; public static final Double NUM_VALUE = 99.0; - public static final String TRANS_1 = "2"; + public static final String TRANS_1 = "t2"; @Autowired private TestHelper testHelper; @Autowired @@ -64,15 +64,12 @@ class RuleEngineTest { @Autowired private FactRepository factRepository; @Autowired - private IUserService userService; - - private LoggedUser superUser; + private SuperCreator superCreator; @BeforeEach public void before() { testHelper.truncateDbs(); - superUser = userService.findByEmail("super@netgrif.com").transformToLoggedUser(); } @AfterEach @@ -89,7 +86,7 @@ void testNetImportRulePRE() throws IOException, MissingPetriNetMetaDataException final String TEST_FIELD = "TEST_FIELD"; StoredRule rule = StoredRule.builder() - .when("$net: PetriNet() $event: NetImportedFact(netId == $net.stringId, eventPhase == com.netgrif.application.engine.petrinet.domain.events.EventPhase.PRE)") + .when("$net: Process() $event: NetImportedFact(netId == $net.stringId, eventPhase == com.netgrif.application.engine.petrinet.domain.events.EventPhase.PRE)") .then("$net.title.defaultValue = \"" + NET_TITLE_PRE + "\"; \n" + "$net.dataSet.put(\"" + TEST_FIELD + "\", new com.netgrif.application.engine.petrinet.domain.dataset.TextField()); \n" + "factRepository.save($event)") @@ -99,14 +96,15 @@ void testNetImportRulePRE() throws IOException, MissingPetriNetMetaDataException .build(); ruleRepository.save(rule); - ImportPetriNetEventOutcome outcome = petriNetService.importPetriNet(new FileInputStream("src/test/resources/rule_engine_test.xml"), VersionType.MAJOR, superUser); + ImportPetriNetEventOutcome outcome = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/rule_engine_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())); - assert outcome.getNet() != null; - assert outcome.getNet().getTitle().getDefaultValue().equals(NET_TITLE_PRE); - assert outcome.getNet().getDataSet().containsKey(TEST_FIELD); - assert outcome.getNet().getDataSet().get(TEST_FIELD) != null; + assert outcome.getProcess() != null; + assert outcome.getProcess().getTitle().getDefaultValue().equals(NET_TITLE_PRE); + assert outcome.getProcess().getDataSet().containsKey(TEST_FIELD); + assert outcome.getProcess().getDataSet().get(TEST_FIELD) != null; - List facts = factRepository.findAll(QNetImportedFact.netImportedFact.netId.eq(outcome.getNet().getStringId()), PageRequest.of(0, 100)).getContent(); + List facts = factRepository.findAll(QNetImportedFact.netImportedFact.netId.eq(outcome.getProcess().getStringId()), PageRequest.of(0, 100)).getContent(); assert facts.size() == 1 && facts.get(0) instanceof NetImportedFact; } @@ -116,8 +114,8 @@ void testNetImportRulePOST() throws IOException, MissingPetriNetMetaDataExceptio final String NEW_INITIALS = "PST"; StoredRule rule = StoredRule.builder() - .when("$net: PetriNet() $event: NetImportedFact(netId == $net.stringId, eventPhase == com.netgrif.application.engine.petrinet.domain.events.EventPhase.PRE)") - .then("$net.initials = \"" + NEW_INITIALS + "\"; \n" + + .when("$net: Process() $event: NetImportedFact(netId == $net.stringId, eventPhase == com.netgrif.application.engine.petrinet.domain.events.EventPhase.PRE)") + .then("$net.title.defaultValue = \"" + NEW_INITIALS + "\"; \n" + "factRepository.save($event)") .identifier("rule1") .lastUpdate(LocalDateTime.now()) @@ -125,24 +123,26 @@ void testNetImportRulePOST() throws IOException, MissingPetriNetMetaDataExceptio .build(); ruleRepository.save(rule); - StoredRule rule2 = StoredRule.builder() - .when("$net: PetriNet() $event: NetImportedFact(netId == $net.stringId, eventPhase == com.netgrif.application.engine.petrinet.domain.events.EventPhase.POST)") - .then("$net.title.defaultValue = \"" + NET_TITLE_POST + "\"; \n factRepository.save($event)") - .identifier("rule2") - .lastUpdate(LocalDateTime.now()) - .enabled(true) - .build(); - ruleRepository.save(rule2); - +// StoredRule rule2 = StoredRule.builder() +// .when("$net: Process() $event: NetImportedFact(netId == $net.stringId, eventPhase == com.netgrif.application.engine.petrinet.domain.events.EventPhase.POST)") +// .then("$net.title.defaultValue = \"" + NET_TITLE_POST + "\"; \n factRepository.save($event)") +// .identifier("rule2") +// .lastUpdate(LocalDateTime.now()) +// .enabled(true) +// .build(); +// ruleRepository.save(rule2); + // TODO: release/8.0.0 refresh stops rules from firing assert refreshableKieBase.shouldRefresh(); - ImportPetriNetEventOutcome outcome = petriNetService.importPetriNet(new FileInputStream("src/test/resources/rule_engine_test.xml"), VersionType.MAJOR, superUser); + ImportPetriNetEventOutcome outcome = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/rule_engine_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())); - assert !refreshableKieBase.shouldRefresh(); +// assert !refreshableKieBase.shouldRefresh(); - assert outcome.getNet() != null; - assert outcome.getNet().getTitle().getDefaultValue().equals(NET_TITLE_POST); - assert outcome.getNet().getInitials().equals(NEW_INITIALS); + assert outcome.getProcess() != null; + assert outcome.getProcess().getTitle().getDefaultValue().equals(NET_TITLE_POST); +// TODO: release/8.0.0 +// assert outcome.getNet().getInitials().equals(NEW_INITIALS); ruleRepository.deleteAll(); factRepository.deleteAll(); @@ -151,13 +151,14 @@ void testNetImportRulePOST() throws IOException, MissingPetriNetMetaDataExceptio @Test void testTransitionRules() throws IOException, MissingPetriNetMetaDataException, TransitionNotExecutableException, MissingIconKeyException { - final String TRANS_1 = "2"; - final String TRANS_2 = "4"; + final String TRANS_1 = "t2"; + final String TRANS_2 = "t4"; final String NEW_CASE_TITLE = "new case title"; final String NEW_CASE_TITLE_2 = "new case title 2"; final String TEXT_VALUE = "TEXT FIELD VALUE"; - ImportPetriNetEventOutcome outcome = petriNetService.importPetriNet(new FileInputStream("src/test/resources/rule_engine_test.xml"), VersionType.MAJOR, superUser); + ImportPetriNetEventOutcome outcome = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/rule_engine_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())); assert outcome != null; StoredRule rule = StoredRule.builder() @@ -197,24 +198,30 @@ void testTransitionRules() throws IOException, MissingPetriNetMetaDataException, ruleRepository.save(rule3); ruleRepository.save(rule4); - CreateCaseEventOutcome caseOutcome = workflowService.createCase(outcome.getNet().getStringId(), "Original title", "original color", superUser); + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(outcome.getProcess()) + .title("Original title") + .authorId(superCreator.getLoggedSuper().getActiveActorId()) + .build(); + CreateCaseEventOutcome caseOutcome = workflowService.createCase(createCaseParams); // TODO: release/8.0.0 AssertionError assert caseOutcome.getCase().getTitle().equals(NEW_CASE_TITLE); Task task = findTask(caseOutcome.getCase(), TRANS_1); - taskService.assignTask(task, superUser.transformToUser()); - taskService.finishTask(task, superUser.transformToUser()); + taskService.assignTask(new TaskParams(task, superCreator.getLoggedSuper().getActiveActorId())); + taskService.finishTask(new TaskParams(task, superCreator.getLoggedSuper().getActiveActorId())); Case newCase = workflowService.findOne(caseOutcome.getCase().getStringId()); assert newCase.getTitle().equals(NEW_CASE_TITLE); - assert !newCase.getColor().equals(NEW_CASE_TITLE_2); +// TODO: release/8.0.0 +// assert !newCase.getColor().equals(NEW_CASE_TITLE_2); List facts = factRepository.findAll(QCaseFact.caseFact.caseId.eq(newCase.getStringId()), PageRequest.of(0, 100)).getContent(); assert facts.size() == 1 && facts.get(0) instanceof TestFact && ((TestFact) facts.get(0)).number == 1; Task task2 = findTask(newCase, TRANS_2); - taskService.assignTask(task2, superUser.transformToUser()); - taskService.finishTask(task2, superUser.transformToUser()); + taskService.assignTask(new TaskParams(task2, superCreator.getLoggedSuper().getActiveActorId())); + taskService.finishTask(new TaskParams(task2, superCreator.getLoggedSuper().getActiveActorId())); newCase = workflowService.findOne(newCase.getStringId()); assert newCase.getTitle().equals(NEW_CASE_TITLE_2); @@ -232,7 +239,7 @@ void assignRuleTest() throws IOException, MissingPetriNetMetaDataException, Tran assert caze != null; Task task = findTask(caze, TRANS_1); - taskService.assignTask(task, superUser.transformToUser()); + taskService.assignTask(new TaskParams(task, superCreator.getLoggedSuper().getActiveActorId())); caze = workflowService.findOne(caze.getStringId()); @@ -253,9 +260,8 @@ void testDelegate() throws IOException, MissingPetriNetMetaDataException, Transi assert caze != null; Task task = findTask(caze, TRANS_1); - IUser user = superUser.transformToUser(); - taskService.assignTask(task, user); - taskService.delegateTask(user.transformToLoggedUser(), user.getStringId(), task.getStringId()); + taskService.assignTask(new TaskParams(task, superCreator.getLoggedSuper().getActiveActorId())); + taskService.delegateTask(superCreator.getLoggedSuper().getActiveActorId(), superCreator.getLoggedSuper().getActiveActorId(), task.getStringId()); caze = workflowService.findOne(caze.getStringId()); assert caze.getDataSet().get("text_data").getValue().getValue().equals(TEXT_VALUE); @@ -274,9 +280,8 @@ void testFinish() throws IOException, MissingPetriNetMetaDataException, Transiti assert caze != null; Task task = findTask(caze, TRANS_1); - IUser user = superUser.transformToUser(); - taskService.assignTask(task, user); - taskService.finishTask(task, user); + taskService.assignTask(new TaskParams(task, superCreator.getLoggedSuper().getActiveActorId())); + taskService.finishTask(new TaskParams(task, superCreator.getLoggedSuper().getActiveActorId())); caze = workflowService.findOne(caze.getStringId()); assert caze.getDataSet().get("text_data").getValue().getValue().equals(TEXT_VALUE); @@ -295,10 +300,9 @@ void testCancel() throws IOException, MissingPetriNetMetaDataException, Transiti assert caze != null; Task task = findTask(caze, TRANS_1); - IUser user = superUser.transformToUser(); - taskService.assignTask(task, user); - taskService.cancelTask(task, user); + taskService.assignTask(new TaskParams(task, superCreator.getLoggedSuper().getActiveActorId())); + taskService.cancelTask(new TaskParams(task, superCreator.getLoggedSuper().getActiveActorId())); caze = workflowService.findOne(caze.getStringId()); assert caze.getDataSet().get("text_data").getValue().getValue().equals(TEXT_VALUE); @@ -374,8 +378,14 @@ private StoredRule rule(String when, String then) { } private Case newCase() throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { - ImportPetriNetEventOutcome outcome = petriNetService.importPetriNet(new FileInputStream("src/test/resources/rule_engine_test.xml"), VersionType.MAJOR, superUser); - return workflowService.createCase(outcome.getNet().getStringId(), "Original title", "original color", superUser).getCase(); + ImportPetriNetEventOutcome outcome = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/rule_engine_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())); + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(outcome.getProcess()) + .title("Original title") + .authorId(superCreator.getLoggedSuper().getActiveActorId()) + .build(); + return workflowService.createCase(createCaseParams).getCase(); } private Task findTask(Case caze, String trans) { diff --git a/src/test/java/com/netgrif/application/engine/rules/service/RuleEvaluationScheduleServiceTest.java b/src/test/java/com/netgrif/application/engine/rules/service/RuleEvaluationScheduleServiceTest.java index 45d67650f99..a043b5aeee1 100644 --- a/src/test/java/com/netgrif/application/engine/rules/service/RuleEvaluationScheduleServiceTest.java +++ b/src/test/java/com/netgrif/application/engine/rules/service/RuleEvaluationScheduleServiceTest.java @@ -1,9 +1,9 @@ package com.netgrif.application.engine.rules.service; import com.netgrif.application.engine.TestHelper; -import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; import com.netgrif.application.engine.petrinet.domain.VersionType; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.rules.domain.RuleRepository; @@ -13,8 +13,9 @@ import com.netgrif.application.engine.rules.service.throwable.RuleEvaluationScheduleException; import com.netgrif.application.engine.startup.SuperCreator; import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.AfterEach; @@ -66,8 +67,8 @@ public void before() { @Test @Disabled void testScheduledRule() throws IOException, MissingPetriNetMetaDataException, RuleEvaluationScheduleException, InterruptedException, MissingIconKeyException { - LoggedUser user = superCreator.getLoggedSuper(); - ImportPetriNetEventOutcome importOutcome = petriNetService.importPetriNet(new FileInputStream("src/test/resources/rule_engine_test.xml"), VersionType.MAJOR, user); + ImportPetriNetEventOutcome importOutcome = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/rule_engine_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())); StoredRule rule = StoredRule.builder() .when("$case: Case() $event: ScheduledRuleFact(instanceId == $case.stringId, ruleIdentifier == \"rule2\")") @@ -78,7 +79,12 @@ void testScheduledRule() throws IOException, MissingPetriNetMetaDataException, R .build(); ruleRepository.save(rule); - CreateCaseEventOutcome caseOutcome = workflowService.createCase(importOutcome.getNet().getStringId(), "Original title", "original color", user); + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(importOutcome.getProcess()) + .title("Original title") + .authorId(superCreator.getLoggedSuper().getActiveActorId()) + .build(); + CreateCaseEventOutcome caseOutcome = workflowService.createCase(createCaseParams); ScheduleOutcome outcome = ruleEvaluationScheduleService.scheduleRuleEvaluationForCase(caseOutcome.getCase(), "rule2", TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).withRepeatCount(5))); assert outcome.getJobDetail() != null; diff --git a/src/test/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationServiceTest.java b/src/test/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationServiceTest.java deleted file mode 100644 index 3d6c910e928..00000000000 --- a/src/test/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationServiceTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.netgrif.application.engine.workflow.service; - -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.User; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import static com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission.*; - -@SpringBootTest -@ActiveProfiles({"test"}) -@ExtendWith(SpringExtension.class) -class AbstractAuthorizationServiceTest { - - static class MockAuthorizationService extends AbstractAuthorizationService { - } - - @Test - public void hasPermission() { - MockAuthorizationService mockInstance = new MockAuthorizationService(); - assert mockInstance.hasPermission(Boolean.TRUE); - assert !mockInstance.hasPermission(Boolean.FALSE); - assert !mockInstance.hasPermission(null); - } - - @Test - public void hasRestrictedPermission() { - MockAuthorizationService mockInstance = new MockAuthorizationService(); - assert !mockInstance.hasRestrictedPermission(Boolean.TRUE); - assert mockInstance.hasRestrictedPermission(Boolean.FALSE); - assert !mockInstance.hasRestrictedPermission(null); - } - - @Test - public void getAggregatePermissions() { - MockAuthorizationService mockInstance = new MockAuthorizationService(); - - // init - List roles = new LinkedList<>(); - roles.add(new ProcessRole()); - roles.add(new ProcessRole()); - roles.add(new ProcessRole()); - - IUser user = new User(); - user.addProcessRole(roles.get(0)); - user.addProcessRole(roles.get(1)); - - Map> netPermissions = new HashMap<>(); - netPermissions.put(roles.get(0).getStringId(), getInitEntryValue()); - netPermissions.put(roles.get(1).getStringId(), getInitEntryValue()); - netPermissions.put(roles.get(2).getStringId(), getInitEntryValue()); - - // situation 1 - Map aggregatePermission = mockInstance.getAggregateProcessRolePermissions(user, netPermissions); - - assert aggregatePermission.get(CREATE); - assert aggregatePermission.get(VIEW); - assert aggregatePermission.get(DELETE); - - // situation 2 - netPermissions.get(roles.get(0).getStringId()).put(CREATE, false); - netPermissions.get(roles.get(1).getStringId()).put(DELETE, false); - aggregatePermission = mockInstance.getAggregateProcessRolePermissions(user, netPermissions); - - // TODO: release/8.0.0 AssertionError - assert !aggregatePermission.get(CREATE); - assert aggregatePermission.get(VIEW); - assert !aggregatePermission.get(DELETE); - } - - private Map getInitEntryValue() { - Map result = new HashMap<>(); - result.put(CREATE, true); - result.put(VIEW, true); - result.put(DELETE, true); - return result; - } -} \ No newline at end of file diff --git a/src/test/java/com/netgrif/application/engine/workflow/service/SystemCaseFactoryRegistryTest.java b/src/test/java/com/netgrif/application/engine/workflow/service/SystemCaseFactoryRegistryTest.java new file mode 100644 index 00000000000..081f8a6079d --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/workflow/service/SystemCaseFactoryRegistryTest.java @@ -0,0 +1,96 @@ +package com.netgrif.application.engine.workflow.service; + +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authorization.domain.Group; +import com.netgrif.application.engine.authorization.domain.User; +import com.netgrif.application.engine.authorization.domain.params.GroupParams; +import com.netgrif.application.engine.authorization.domain.params.UserParams; +import com.netgrif.application.engine.authorization.service.interfaces.IGroupService; +import com.netgrif.application.engine.authorization.service.interfaces.IUserService; +import com.netgrif.application.engine.petrinet.domain.Process; +import com.netgrif.application.engine.petrinet.domain.VersionType; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; +import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.startup.ImportHelper; +import com.netgrif.application.engine.startup.SuperCreator; +import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.SystemCase; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.io.FileInputStream; +import java.io.IOException; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class SystemCaseFactoryRegistryTest { + + @Autowired + private SystemCaseFactoryRegistry registry; + + @Autowired + private IWorkflowService workflowService; + + @Autowired + private SuperCreator superCreator; + + @Autowired + private IUserService userService; + + @Autowired + private IGroupService groupService; + + @Autowired + private IPetriNetService petriNetService; + + @Autowired + private TestHelper testHelper; + + @Autowired + private ImportHelper importHelper; + + @BeforeEach + public void before() { + testHelper.truncateDbs(); + } + + @Test + public void testFromCase() throws IOException, MissingPetriNetMetaDataException { + assert registry.fromCase(null) == null; + + TestHelper.login(superCreator.getSuperIdentity()); + + Process testProcess = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/all_data.xml"), + VersionType.MAJOR, superCreator.getSuperIdentity().getMainActorId())).getProcess(); + Case testCase = importHelper.createCase("Test", testProcess); + + assert registry.fromCase(workflowService.findOne(testCase.getStringId())) == null; + + User user = userService.create(UserParams.with() + .email(new TextField("s@meemail.com")) + .build()); + + SystemCase systemCase = registry.fromCase(user.getCase()); + assert systemCase != null; + assert systemCase instanceof User; + assert systemCase.getCase().getStringId().equals(user.getStringId()); + + Group group = groupService.create(GroupParams.with() + .name(new TextField("group name")) + .build()); + + systemCase = registry.fromCase(group.getCase()); + assert systemCase != null; + assert systemCase instanceof Group; + assert systemCase.getCase().getStringId().equals(group.getStringId()); + } +} diff --git a/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java b/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java index 59983f22c1f..9cd30b228d1 100644 --- a/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java +++ b/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java @@ -1,42 +1,45 @@ package com.netgrif.application.engine.workflow.service; -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.domain.User; -import com.netgrif.application.engine.auth.domain.UserState; -import com.netgrif.application.engine.auth.domain.repositories.UserRepository; -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; -import com.netgrif.application.engine.configuration.properties.SuperAdminConfiguration; +import com.netgrif.application.engine.MockService; +import com.netgrif.application.engine.TestHelper; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.LoggedIdentity; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.VersionType; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository; import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.startup.ImportHelper; import com.netgrif.application.engine.startup.SuperCreator; -import com.netgrif.application.engine.startup.SystemUserRunner; -import com.netgrif.application.engine.startup.UriRunner; import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.QCase; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.TaskParams; import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository; import com.netgrif.application.engine.workflow.domain.repositories.TaskRepository; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; -import org.bson.types.ObjectId; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.io.FileInputStream; import java.io.IOException; -import java.util.Collections; +import java.util.ArrayList; +import java.util.Objects; + +import static org.junit.jupiter.api.Assertions.assertThrows; @SpringBootTest @ActiveProfiles({"test"}) @@ -46,6 +49,9 @@ public class TaskServiceTest { @Autowired private ITaskService service; + @Autowired + private MockService mockService; + @Autowired private IWorkflowService workflowService; @@ -59,19 +65,7 @@ public class TaskServiceTest { private TaskRepository taskRepository; @Autowired - private MongoTemplate mongoTemplate; - - @Autowired - private UserRepository userRepository; - - @Autowired - private IAuthorityService authorityService; - - @Autowired - private SystemUserRunner userRunner; - - @Autowired - private UriRunner uriRunner; + private ImportHelper importHelper; @Autowired private IPetriNetService petriNetService; @@ -80,58 +74,208 @@ public class TaskServiceTest { private SuperCreator superCreator; @Autowired - private SuperAdminConfiguration configuration; + private TestHelper testHelper; + + @Autowired + private TaskService taskService; @BeforeEach public void setUp() throws Exception { - mongoTemplate.getDb().drop(); - taskRepository.deleteAll(); - userRunner.run(""); - uriRunner.run(); - - petriNetService.importPetriNet(new FileInputStream("src/test/resources/prikladFM.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()); - PetriNet net = petriNetRepository.findAll().get(0); - workflowService.createCase(net.getStringId(), "Storage Unit", "color", mockLoggedUser()); + testHelper.truncateDbs(); + + petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/prikladFM.xml"), VersionType.MAJOR, + superCreator.getLoggedSuper().getActiveActorId())); + Process net = petriNetRepository.findAll().get(0); + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Storage Unit") + .authorId(mockService.mockLoggedIdentity().getActiveActorId()) + .build(); + workflowService.createCase(createCaseParams); + TestHelper.login(superCreator.getSuperIdentity()); } @Test public void resetArcTest() throws TransitionNotExecutableException, MissingPetriNetMetaDataException, IOException, MissingIconKeyException { - PetriNet net = petriNetService.importPetriNet(new FileInputStream("src/test/resources/reset_inhibitor_test.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()).getNet(); - LoggedUser loggedUser = mockLoggedUser(); - CreateCaseEventOutcome outcome = workflowService.createCase(net.getStringId(), "Reset test", "color", loggedUser); - User user = new User(); - user.setName("name"); - user.setPassword("password"); - user.setSurname("surname"); - user.setEmail("email@email.com"); - user.setState(UserState.ACTIVE); - user = userRepository.save(user); - - assert outcome.getCase().getConsumedTokens().size() == 0; + Process net = petriNetService.importProcess(new ImportProcessParams(new FileInputStream("src/test/resources/reset_inhibitor_test.xml"), + VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess(); + LoggedIdentity mockedLoggedIdentity = mockService.mockLoggedIdentity(); + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(net) + .title("Reset test") + .authorId(mockedLoggedIdentity.getActiveActorId()) + .build(); + CreateCaseEventOutcome outcome = workflowService.createCase(createCaseParams); + + Identity identity = importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("firstname")) + .lastname(new TextField("lastname")) + .password(new TextField("password")) + .username(new TextField("email@email.com")) + .build(), new ArrayList<>()); + + assert outcome.getCase().getConsumedTokens().isEmpty(); assert outcome.getCase().getActivePlaces().size() == 1; - assert outcome.getCase().getActivePlaces().values().contains(5); + assert outcome.getCase().getActivePlaces().containsValue(5); Task task = taskRepository.findAll().stream().filter(t -> t.getTitle().getDefaultValue().equalsIgnoreCase("reset")).findFirst().orElse(null); assert task != null; - service.assignTask(user.transformToLoggedUser(), task.getStringId()); + service.assignTask(new TaskParams(task.getStringId(), identity.toSession().getActiveActorId())); Case useCase = caseRepository.findById(outcome.getCase().getStringId()).get(); assert useCase.getConsumedTokens().size() == 1; - assert useCase.getConsumedTokens().values().contains(5); - assert useCase.getActivePlaces().size() == 0; + assert useCase.getConsumedTokens().containsValue(5); + assert useCase.getActivePlaces().isEmpty(); - service.cancelTask(user.transformToLoggedUser(), task.getStringId()); + service.cancelTask(new TaskParams(task.getStringId(), identity.toSession().getActiveActorId())); useCase = caseRepository.findById(useCase.getStringId()).get(); - assert useCase.getConsumedTokens().size() == 0; + assert useCase.getConsumedTokens().isEmpty(); assert useCase.getActivePlaces().size() == 1; - assert useCase.getActivePlaces().values().contains(5); + assert useCase.getActivePlaces().containsValue(5); + } + + @Test + public void testTransactionalAssignTaskFailure() throws IOException, MissingPetriNetMetaDataException { + String taskId = createCaseAndReturnTaskId("src/test/resources/transactional_task_event_test.xml", + "assignTest"); + + TaskParams taskParams = TaskParams.with() + .isTransactional(true) + .taskId(taskId) + .assigneeId(superCreator.getLoggedSuper().getActiveActorId()) + .build(); + + assertThrows(RuntimeException.class, () -> taskService.assignTask(taskParams)); + + Task aTask = taskService.findOne(taskId); + assert aTask.getAssigneeId() == null; + assert workflowService.searchOne(QCase.case$.title.eq("CasePre")) == null; + assert workflowService.searchOne(QCase.case$.title.eq("CasePost")) == null; } - public LoggedUser mockLoggedUser() { - Authority authorityUser = authorityService.getOrCreate(Authority.user); - return new LoggedUser(new ObjectId().toString(), configuration.getEmail(), configuration.getPassword(), Collections.singleton(authorityUser)); + @Test + public void testNonTransactionalAssignTaskFailure() throws IOException, MissingPetriNetMetaDataException { + String taskId = createCaseAndReturnTaskId("src/test/resources/transactional_task_event_test.xml", + "assignTest"); + + TaskParams taskParams = TaskParams.with() + .isTransactional(false) + .taskId(taskId) + .assigneeId(superCreator.getLoggedSuper().getActiveActorId()) + .build(); + + assertThrows(RuntimeException.class, () -> taskService.assignTask(taskParams)); + + Task aTask = taskService.findOne(taskId); + assert aTask.getAssigneeId() != null; + assert workflowService.searchOne(QCase.case$.title.eq("CasePre")) != null; + assert workflowService.searchOne(QCase.case$.title.eq("CasePost")) != null; + } + + @Test + public void testTransactionalCancelTaskFailure() throws IOException, MissingPetriNetMetaDataException, TransitionNotExecutableException { + String taskId = createCaseAndReturnTaskId("src/test/resources/transactional_task_event_test.xml", + "cancelTest"); + + TaskParams taskParams = TaskParams.with() + .isTransactional(false) + .taskId(taskId) + .assigneeId(superCreator.getLoggedSuper().getActiveActorId()) + .build(); + + Task aTask = taskService.assignTask(taskParams).getTask(); + assert Objects.equals(aTask.getAssigneeId(), superCreator.getLoggedSuper().getActiveActorId()); + + taskParams.setIsTransactional(true); + assertThrows(RuntimeException.class, () -> taskService.cancelTask(taskParams)); + + aTask = taskService.findOne(taskId); + assert Objects.equals(aTask.getAssigneeId(), superCreator.getLoggedSuper().getActiveActorId()); + assert workflowService.searchOne(QCase.case$.title.eq("CasePre")) == null; + assert workflowService.searchOne(QCase.case$.title.eq("CasePost")) == null; + } + + @Test + public void testNonTransactionalCancelTaskFailure() throws IOException, MissingPetriNetMetaDataException, TransitionNotExecutableException { + String taskId = createCaseAndReturnTaskId("src/test/resources/transactional_task_event_test.xml", + "cancelTest"); + + TaskParams taskParams = TaskParams.with() + .isTransactional(false) + .taskId(taskId) + .assigneeId(superCreator.getLoggedSuper().getActiveActorId()) + .build(); + + Task aTask = taskService.assignTask(taskParams).getTask(); + assert Objects.equals(aTask.getAssigneeId(), superCreator.getLoggedSuper().getActiveActorId()); + + assertThrows(RuntimeException.class, () -> taskService.cancelTask(taskParams)); + + aTask = taskService.findOne(taskId); + assert aTask.getAssigneeId() == null; + assert workflowService.searchOne(QCase.case$.title.eq("CasePre")) != null; + assert workflowService.searchOne(QCase.case$.title.eq("CasePost")) != null; + } + + @Test + public void testTransactionalFinishTaskFailure() throws IOException, MissingPetriNetMetaDataException, TransitionNotExecutableException { + String taskId = createCaseAndReturnTaskId("src/test/resources/transactional_task_event_test.xml", + "finishTest"); + + TaskParams taskParams = TaskParams.with() + .isTransactional(false) + .taskId(taskId) + .assigneeId(superCreator.getLoggedSuper().getActiveActorId()) + .build(); + + Task aTask = taskService.assignTask(taskParams).getTask(); + assert Objects.equals(aTask.getAssigneeId(), superCreator.getLoggedSuper().getActiveActorId()); + + taskParams.setIsTransactional(true); + assertThrows(RuntimeException.class, () -> taskService.finishTask(taskParams)); + + aTask = taskService.findOne(taskId); + assert Objects.equals(aTask.getAssigneeId(), superCreator.getLoggedSuper().getActiveActorId()); + assert aTask.getFinishedBy() == null; + assert workflowService.searchOne(QCase.case$.title.eq("CasePre")) == null; + assert workflowService.searchOne(QCase.case$.title.eq("CasePost")) == null; + } + + @Test + public void testNonTransactionalFinishTaskFailure() throws IOException, MissingPetriNetMetaDataException, TransitionNotExecutableException { + String taskId = createCaseAndReturnTaskId("src/test/resources/transactional_task_event_test.xml", + "finishTest"); + + TaskParams taskParams = TaskParams.with() + .isTransactional(false) + .taskId(taskId) + .assigneeId(superCreator.getLoggedSuper().getActiveActorId()) + .build(); + + Task aTask = taskService.assignTask(taskParams).getTask(); + assert Objects.equals(aTask.getAssigneeId(), superCreator.getLoggedSuper().getActiveActorId()); + + assertThrows(RuntimeException.class, () -> taskService.finishTask(taskParams)); + + aTask = taskService.findOne(taskId); + assert aTask.getAssigneeId() == null; + assert aTask.getFinishedBy().equals(superCreator.getLoggedSuper().getActiveActorId()); + assert workflowService.searchOne(QCase.case$.title.eq("CasePre")) != null; + assert workflowService.searchOne(QCase.case$.title.eq("CasePost")) != null; + } + + private String createCaseAndReturnTaskId(String filePath, String transId) throws IOException, MissingPetriNetMetaDataException { + Process process = petriNetService.importProcess(new ImportProcessParams( + new FileInputStream(filePath), VersionType.MAJOR, superCreator.getLoggedSuper().getActiveActorId())).getProcess(); + + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(process) + .authorId(superCreator.getLoggedSuper().getActiveActorId()) + .build(); + Case useCase = workflowService.createCase(createCaseParams).getCase(); + return useCase.getTaskStringId(transId); } } \ No newline at end of file diff --git a/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java b/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java index 0de83af0a03..fa5b736e1d0 100644 --- a/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java +++ b/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java @@ -2,30 +2,29 @@ import com.netgrif.application.engine.MockService; import com.netgrif.application.engine.TestHelper; -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.User; -import com.netgrif.application.engine.auth.domain.UserState; -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; +import com.netgrif.application.engine.authentication.domain.Identity; +import com.netgrif.application.engine.authentication.domain.params.IdentityParams; +import com.netgrif.application.engine.authorization.service.interfaces.IRoleService; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; -import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.Process; import com.netgrif.application.engine.petrinet.domain.VersionType; -import com.netgrif.application.engine.petrinet.domain.arcs.Arc; +import com.netgrif.application.engine.petrinet.domain.arcs.ArcCollection; import com.netgrif.application.engine.petrinet.domain.dataset.NumberField; +import com.netgrif.application.engine.petrinet.domain.dataset.TextField; +import com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams; import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository; -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole; import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; -import com.netgrif.application.engine.startup.DefaultRoleRunner; import com.netgrif.application.engine.startup.ImportHelper; import com.netgrif.application.engine.startup.SuperCreator; import com.netgrif.application.engine.startup.SystemUserRunner; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.QTask; import com.netgrif.application.engine.workflow.domain.Task; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; -import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.outcomes.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; +import com.netgrif.application.engine.workflow.domain.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.domain.params.TaskParams; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import com.netgrif.application.engine.workflow.web.responsebodies.TaskReference; @@ -40,8 +39,10 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import java.io.FileInputStream; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -69,14 +70,11 @@ public class VariableArcsTest { private MockService mock; @Autowired - private IProcessRoleService processRoleService; + private IRoleService roleService; @Autowired private ImportHelper importHelper; - @Autowired - private IAuthorityService authorityService; - @Autowired private SystemUserRunner userRunner; @@ -86,9 +84,9 @@ public class VariableArcsTest { @Autowired private TestHelper testHelper; - private PetriNet loaded; + private Process loaded; - private IUser testUser; + private Identity testIdentity; private Case finishCase; @@ -99,22 +97,23 @@ public void before() throws Exception { testHelper.truncateDbs(); userRunner.run(""); repository.deleteAll(); - assertNotNull(processRoleService.defaultRole()); + assertNotNull(roleService.findDefaultRole()); testHelper.truncateDbs(); - ImportPetriNetEventOutcome outcome = service.importPetriNet(new FileInputStream(NET_PATH), VersionType.MAJOR, superCreator.getLoggedSuper()); + ImportPetriNetEventOutcome outcome = service.importProcess(new ImportProcessParams(new FileInputStream(NET_PATH), VersionType.MAJOR, + superCreator.getLoggedSuper().getActiveActorId())); - assert outcome.getNet() != null; - PetriNet net = outcome.getNet(); + assert outcome.getProcess() != null; + Process net = outcome.getProcess(); this.loaded = service.getPetriNet(net.getStringId()); - User user = new User(); - user.setName("Test"); - user.setSurname("Test"); - user.setPassword("password"); - user.setState(UserState.ACTIVE); - user.setEmail("VariableArcsTest@test.com"); - testUser = importHelper.createUser(user, - new Authority[]{authorityService.getOrCreate(Authority.user)}, - new ProcessRole[]{}); + + testIdentity = importHelper.createIdentity(IdentityParams.with() + .firstname(new TextField("Test")) + .lastname(new TextField("Test")) + .password(new TextField("password")) + .username(new TextField("VariableArcsTest@test.com")) + .build(), new ArrayList<>()); + + TestHelper.login(superCreator.getSuperIdentity()); finishCase = importHelper.createCase("finish case", loaded); cancelCase = importHelper.createCase("assign case", loaded); @@ -122,17 +121,20 @@ public void before() throws Exception { @Test public void importTest() throws MissingIconKeyException { - - List arcs = this.loaded.getArcs().values().stream().flatMap(List::stream).collect(Collectors.toList()); - assert arcs.size() > 0; - CreateCaseEventOutcome caseOutcome = workflowService.createCase(this.loaded.getStringId(), "VARTEST", "red", mock.mockLoggedUser()); - - assert caseOutcome.getCase().getPetriNet().getArcs() + int count = this.loaded.getArcs().values().stream().map(ArcCollection::size).reduce(Integer::sum).orElse(0); + assert count > 0; + CreateCaseParams createCaseParams = CreateCaseParams.with() + .process(this.loaded) + .title("VARTEST") + .authorId(mock.mockLoggedIdentity().getActiveActorId()) + .build(); + CreateCaseEventOutcome caseOutcome = workflowService.createCase(createCaseParams); + assert caseOutcome.getCase().getProcess().getArcs() .values() .stream() - .flatMap(List::stream) - .filter(arc -> arc.getReference() != null) - .allMatch(arc -> arc.getReference().getReferencable() != null); + .flatMap(arcCollection -> Stream.concat(arcCollection.getInput().stream(), arcCollection.getOutput().stream())) + .filter(arc -> arc.getMultiplicityExpression() != null) + .allMatch(arc -> arc.getMultiplicityExpression().getMultiplicity() != null); } @Test @@ -148,11 +150,11 @@ public void finishTasksTest() throws TransitionNotExecutableException { private void assertInhibArcsFinishTask(List tasks) throws TransitionNotExecutableException { for (TaskReference taskRef : tasks) { Task task = taskService.findOne(taskRef.getStringId()); - taskService.assignTask(task, testUser); + taskService.assignTask(new TaskParams(task, testIdentity.toSession().getActiveActorId())); finishCase = workflowService.findOne(task.getCaseId()); assert !finishCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_start") && !finishCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_res"); - taskService.finishTask(task, testUser); + taskService.finishTask(new TaskParams(task, testIdentity.toSession().getActiveActorId())); finishCase = workflowService.findOne(task.getCaseId()); assert !finishCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_start") && finishCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_res"); @@ -164,12 +166,12 @@ private void assertReadArcsFinishTask(List tasks) throws Transiti Task task = taskService.findOne(taskRef.getStringId()); int markingBeforeAssign = 0; markingBeforeAssign = finishCase.getActivePlaces().get(task.getTitle().getDefaultValue() + "_start"); - taskService.assignTask(task, testUser); + taskService.assignTask(new TaskParams(task, testIdentity.toSession().getActiveActorId())); finishCase = workflowService.findOne(task.getCaseId()); assert markingBeforeAssign == finishCase.getActivePlaces().get(task.getTitle().getDefaultValue() + "_start"); - taskService.finishTask(task, testUser); + taskService.finishTask(new TaskParams(task, testIdentity.toSession().getActiveActorId())); finishCase = workflowService.findOne(task.getCaseId()); assert markingBeforeAssign == finishCase.getActivePlaces().get(task.getTitle().getDefaultValue() + "_start") && @@ -181,13 +183,13 @@ private void assertFinishTasks(String arcType, List tasks) throws List filteredTasks = tasks.stream().filter(task -> task.getTitle().contains(arcType)).collect(Collectors.toList()); for (TaskReference taskRef : filteredTasks) { Task task = taskService.findOne(taskRef.getStringId()); - taskService.assignTask(task, testUser); + taskService.assignTask(new TaskParams(task, testIdentity.toSession().getActiveActorId())); finishCase = workflowService.findOne(task.getCaseId()); // TODO: release/8.0.0 assert !finishCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_start"); - taskService.finishTask(task, testUser); + taskService.finishTask(new TaskParams(task, testIdentity.toSession().getActiveActorId())); finishCase = workflowService.findOne(task.getCaseId()); assert !finishCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_start") && @@ -199,12 +201,12 @@ private void assertOutArcsFinishTasks(List tasks) throws Transiti List filteredTasks = tasks.stream().filter(task -> task.getTitle().equals("var_arc_out") || task.getTitle().equals("place_var_arc_out")).collect(Collectors.toList()); for (TaskReference taskRef : filteredTasks) { Task task = taskService.findOne(taskRef.getStringId()); - taskService.assignTask(task, testUser); + taskService.assignTask(new TaskParams(task, testIdentity.toSession().getActiveActorId())); finishCase = workflowService.findOne(task.getCaseId()); assert !finishCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_end"); - taskService.finishTask(task, testUser); + taskService.finishTask(new TaskParams(task, testIdentity.toSession().getActiveActorId())); finishCase = workflowService.findOne(task.getCaseId()); assert finishCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_end") && @@ -240,7 +242,7 @@ private void assertCancelTasks(String arcType, List tasks) throws if (!arcType.equals("inhib")) { tokensBeforeAssign = cancelCase.getActivePlaces().get(task.getTitle().getDefaultValue() + "_start"); } - taskService.assignTask(task, testUser); + taskService.assignTask(new TaskParams(task, testIdentity.toSession().getActiveActorId())); cancelCase = workflowService.findOne(task.getCaseId()); assert !cancelCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_res"); if (arcType.equals("read")) { @@ -250,19 +252,19 @@ private void assertCancelTasks(String arcType, List tasks) throws assert !cancelCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_start"); } if (task.getTitle().getDefaultValue().contains("var")) { - dataRefMultiplicityBeforeChange = Double.parseDouble(cancelCase.getDataSet().get(arcType + "_var").getValue().toString()); - NumberField varArcReference = (NumberField) cancelCase.getDataSet().get(arcType + "_var"); + dataRefMultiplicityBeforeChange = Double.parseDouble(cancelCase.getDataSet().get(arcType + "_var_field").getValue().toString()); + NumberField varArcReference = (NumberField) cancelCase.getDataSet().get(arcType + "_var_field"); varArcReference.setRawValue(800d); workflowService.save(cancelCase); } if (task.getTitle().getDefaultValue().contains("ref")) { QTask qTask = new QTask("task"); Task addTokensTask = taskService.searchOne(qTask.transitionId.eq("add_tokens").and(qTask.caseId.eq(cancelCase.getStringId()))); - taskService.assignTask(testUser.transformToLoggedUser(), addTokensTask.getStringId()); - taskService.finishTask(addTokensTask, testUser); + taskService.assignTask(new TaskParams(testIdentity.toSession().getActiveActorId(), addTokensTask.getStringId())); + taskService.finishTask(new TaskParams(addTokensTask, testIdentity.toSession().getActiveActorId())); } int tokensAfterCancel = 0; - taskService.cancelTask(task, testUser); + taskService.cancelTask(new TaskParams(task, testIdentity.toSession().getActiveActorId())); cancelCase = workflowService.findOne(task.getCaseId()); if (!arcType.equals("inhib")) { tokensAfterCancel = cancelCase.getActivePlaces().get(task.getTitle().getDefaultValue() + "_start"); @@ -276,15 +278,15 @@ private void assertCancelTasks(String arcType, List tasks) throws } if (task.getTitle().getDefaultValue().contains("var")) { - NumberField varArcReference = (NumberField) cancelCase.getDataSet().get(arcType + "_var"); + NumberField varArcReference = (NumberField) cancelCase.getDataSet().get(arcType + "_var_field"); varArcReference.setRawValue(dataRefMultiplicityBeforeChange); workflowService.save(cancelCase); } if (task.getTitle().getDefaultValue().contains("ref")) { QTask qTask = new QTask("task"); Task removeTokensTask = taskService.searchOne(qTask.transitionId.eq("remove_tokens").and(qTask.caseId.eq(cancelCase.getStringId()))); - taskService.assignTask(testUser.transformToLoggedUser(), removeTokensTask.getStringId()); - taskService.finishTask(removeTokensTask, testUser); + taskService.assignTask(new TaskParams(testIdentity.toSession().getActiveActorId(), removeTokensTask.getStringId())); + taskService.finishTask(new TaskParams(removeTokensTask, testIdentity.toSession().getActiveActorId())); tasksAfterPlaceRefReset = taskService.findAllByCase(cancelCase.getStringId(), LocaleContextHolder.getLocale()); } } @@ -294,12 +296,12 @@ private void assertOutArcsCancelTasks(List tasks) throws Transiti List filteredTasks = tasks.stream().filter(task -> task.getTitle().equals("var_arc_out") || task.getTitle().equals("place_var_arc_out")).collect(Collectors.toList()); for (TaskReference taskRef : filteredTasks) { Task task = taskService.findOne(taskRef.getStringId()); - taskService.assignTask(task, testUser); + taskService.assignTask(new TaskParams(task, testIdentity.toSession().getActiveActorId())); cancelCase = workflowService.findOne(task.getCaseId()); assert !cancelCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_end"); - taskService.cancelTask(task, testUser); + taskService.cancelTask(new TaskParams(task, testIdentity.toSession().getActiveActorId())); cancelCase = workflowService.findOne(task.getCaseId()); assert !cancelCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_res"); diff --git a/src/test/resources/actionref_test.xml b/src/test/resources/actionref_test.xml index 16ec8c1d9d7..02ea34f4100 100644 --- a/src/test/resources/actionref_test.xml +++ b/src/test/resources/actionref_test.xml @@ -1,128 +1,95 @@ - - - actionref_test.xml - TST + + actionref_test + 1.0.0 Test - - + false + false + + TST + + + text_1 Text 1 - - field: f.text_1; - def a = "data_action_set"; - - - field: f.text_1; - def a = "data_action_get"; - - - data_action_set - - - data_action_get - - - dataref_action_set - - - dataref_action_get - - - event_action_pre - - - event_action_post - + + text_1_set + + + + + + + + text_1_get + + + + + + - task 0 0 - - - text_1 - - - field: f.text_1; - def a = "dataref_action_get"; - - - field: f.text_1; - def a = "dataref_action_set"; - - - data_action_set - - - data_action_get - - - dataref_action_set - - - dataref_action_get - - - event_action_pre - - - event_action_post - - - + Task + + task_flex + + + text_1 + + editable + + + text_1_ref_get + + + + + + + + text_1_ref_set + + + + + + + + + 0 + 0 + 1 + + + onFinish - field: f.text_1; + - - data_action_set - - - data_action_get - - - dataref_action_set - - - dataref_action_get - - - event_action_pre - - - event_action_post - + ]]> + - field: f.text_1; + - - data_action_set - - - data_action_get - - - dataref_action_set - - - dataref_action_get - - - event_action_pre - - - event_action_post - + ]]> + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/agreement.xml b/src/test/resources/agreement.xml index 4d585489a22..806f2853c4f 100644 --- a/src/test/resources/agreement.xml +++ b/src/test/resources/agreement.xml @@ -1,11 +1,15 @@ - - Agreement - Agr + + agreement + 1.0.0 Agreement device_hub true true - false + + Agr + + + contract_name Contract name @@ -16,10 +20,9 @@ <init>Customer details</init> </data> - <data type="taskRef"> - <id>taskRef_0</id> - <title/> - <init>t1</init> + <data type="text"> + <id>decision_result</id> + <title>Agreement decision issue_type @@ -29,6 +32,11 @@ + + taskRef_0 + + <init>t1</init> + </data> <data type="taskRef"> <id>taskRef_1</id> <title/> @@ -39,154 +47,132 @@ <title/> <init>t13</init> </data> - <data type="text"> - <id>decision_result</id> - <title>Agreement decision - t1 60 340 - - - 0 - - - t1_0 - 4 - grid - - contract_name - - editable - - - 0 - 0 - 1 - 3 - - outline - - - - customer_details - - visible - - - 2 - 2 - 1 - 2 - - standard - - - + contract + + t1_flex + + + contract_name + + editable + + + + 0 + 0 + 1 + + + + + customer_details + + visible + + + + 0 + 0 + 1 + + + + + + t13 + 60 + 500 + result + + t13_flex + + + decision_result + + visible + + + + 0 + 0 + 1 + + + t4 60 420 - - - t4_0 - 4 - grid - - issue_type - - editable - required - - - 0 - 2 - 1 - 2 - - outline - - - + comment + + t4_flex + + + issue_type + + editable + true + + + + 0 + 0 + 1 + + + t6 140 340 - - - t6_0 - 4 - grid - - taskRef_1 - - visible - - - 0 - 1 - 1 - 4 - - outline - - - - taskRef_0 - - visible - - - 0 - 2 - 1 - 4 - - outline - - - - taskRef_result - - visible - - - 0 - 0 - 1 - 4 - - outline - - - - - - t13 - 60 - 500 - - - t13_0 - 4 - grid - - decision_result - - visible - - - 0 - 0 - 1 - 4 - - outline - - - + summary A + + t6_flex + + + taskRef_1 + + visible + + + + 0 + 0 + 1 + + + + + taskRef_0 + + visible + + + + 0 + 0 + 1 + + + + + taskRef_result + + visible + + + + 0 + 0 + 1 + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/all_data.xml b/src/test/resources/all_data.xml index 261a5670d88..d49dfa658f5 100644 --- a/src/test/resources/all_data.xml +++ b/src/test/resources/all_data.xml @@ -1,9 +1,12 @@ - - + all_data + 1.0.0 All Data - ALL - + false + false + + ALL + process_role Process role @@ -12,680 +15,570 @@ process_role2 Process role2 - - - number - Number - 10000 + + boolean + Boolean - - number_currency - Number currency - 10000 - - - EUR - 2 - sk_SK - - + + button + Button + Push - - - text - Text - Lorem ipsum + + date + Date + 2019-01-01 - - text_area - Text area - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vitae magna in libero semper - vulputate ut eu sapien. Phasellus vel. - + + datetime + Datetime + 2019-01-01T20:00:00.000Z - enumeration Enumeration - Alice - Bob - Carol + + + + + Bob enumeration_autocomplete Enumeration autocomplete - Alice - Bob - Carol + + + + + Bob - - - + + autocomplete + enumeration_list Enumeration list - Alice - Bob - Carol + + + + + Bob - - - - - - - multichoice - Multichoice - Alice - Bob - Carol - Carol - - - multichoice_list - Multichoice list - Alice - Bob - Carol - Alice,Bob - - - - - - - boolean - Boolean - - - - date - Date - 01.01.2019 - - - - file - File - pom.xml - - - - user - User - - - - datetime - Datetime - 01.01.2019 20:00 + + list + - enumeration_map Enumeration map - - - + + + bob - - - multichoice_map - Multichoice map + + enumeration_map_changed + Enumeration map changed - - - + + + - carol + bob + + + file + File + pom.xml - fileList File list - - - - userList - User list - + + i18n_divider + Divider I18n + Divider I18n field + Default i18n divider value + + divider + - - - button - Button - Push + + i18n_text + Text I18n + Text I18n field + Default i18n text value - - - testActionTrigger - Test Action Trigger + + multichoice + Multichoice + + + + + + Carol - - - enumeration_map_changed - Enumeration map changed + + multichoice_list + Multichoice list - - - + + + - bob + Alice,Bob + + list + + + + multichoice_map + Multichoice map + + + + + + carol - multichoice_map_changed Multichoice map changed - - - + + + carol - - - i18n_text - Text I18n - Text I18n field - Default i18n text value + + number + Number + 10000 - - - i18n_divider - Divider I18n - Divider I18n field - Default i18n divider value + + number_currency + Number currency + 10000 - divider + currency + + sk_SK + EUR + 2 + - - + + testActionTrigger + Test Action Trigger + + + text + Text + Lorem ipsum + + + text_area + Text area + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vitae magna in libero semper + vulputate ut eu sapien. Phasellus vel. + + + user + User + + + userList + User list + - Alica - Bobek - Karla - Default SK i18n text value - Default SK i18n divider value + Alica + Bobek + Karla + Default SK i18n text value + Default SK i18n divider value - - - 1 + t1 379 273 - 6 - + Task - editable auto - - number - Number fields - false - 2 - - number - - editable - - - - number_currency - - editable - - - - - text - Text fields - false - - text - - editable - - - - text_area - - editable - - - - - enumeration - Enumeration fields - false - - enumeration - - editable - - - - enumeration_autocomplete - - editable - - - - enumeration_list - - editable - - - - - multichoice - Multichoice fields - false - - multichoice - - editable - - - - multichoice_list - - editable - - - - - boolean - Boolean fields - false - - boolean - - editable - - - - - date - Date fields - false - - date - - editable - - - - datetime - - editable - - - - - file - File fields - false - - file - - editable - - - - - user - User fields - false - - user - - editable - - - - - button - Button fields - false - - button - - editable - - - - - i18n - I18n fields - false - - i18n_text - - editable - - - - i18n_divider - - editable - - - + + t1_flex + + + number + + editable + + + + + + number_currency + + editable + + + + + + text + + editable + + + + + + text_area + + editable + + + + + + enumeration + + editable + + + + + + enumeration_autocomplete + + editable + + + + + + enumeration_list + + editable + + + + + + multichoice + + editable + + + + + + multichoice_list + + editable + + + + + + boolean + + editable + + + + + + date + + editable + + + + + + datetime + + editable + + + + + + file + + editable + + + + + + user + + editable + + + + + + button + + editable + + + + + + i18n_text + + editable + + + + + + i18n_divider + + editable + + + + - 2 + t2 379 273 - + Task - visible auto - - number - Number fields - false - - number - - visible - - - - number_currency - - visible - - - - - text - Text fields - false - - text - - visible - - - - text_area - - visible - - - - - enumeration - Enumeration fields - false - - enumeration - - visible - - - - enumeration_autocomplete - - visible - - - - enumeration_list - - visible - - - - - multichoice - Multichoice fields - false - - multichoice - - visible - - - - multichoice_list - - visible - - - - - boolean - Boolean fields - false - - boolean - - visible - - - - - date - Date fields - false - - date - - visible - - - - datetime - - visible - - - - - file - File fields - false - - file - - visible - - - - - user - User fields - false - - user - - visible - - - - - button - Button fields - false - - button - - visible - - - - - i18n - I18n fields - false - - i18n_text - - visible - - - - i18n_divider - - visible - - - + + t2_flex + + + number + + editable + + + + + + number_currency + + editable + + + + + + text + + editable + + + + + + text_area + + editable + + + + + + enumeration + + editable + + + + + + enumeration_autocomplete + + editable + + + + + + enumeration_list + + editable + + + + + + multichoice + + editable + + + + + + multichoice_list + + editable + + + + + + boolean + + editable + + + + + + date + + editable + + + + + + datetime + + editable + + + + + + file + + editable + + + + + + user + + editable + + + + + + button + + editable + + + + + + i18n_text + + editable + + + + + + i18n_divider + + editable + + + + - 3 + t3 379 273 - + Datagroups auto - - stretch - Stretch - start - true - - text - - visible - - - - number - - editable - - - - enumeration - - editable - - - - - right - Alignment - Right - end - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - - - left - Alignment - Left - start - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - - - center - Alignment - Center - center - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - + + t3_flex + + + text + + editable + + + + + + number + + editable + + + + + + enumeration + + editable + + + + - 2 + t4 500 300 - 6 - + Test Action trigger auto - - testActionTrigger - - visible - - - enumMap: f.enumeration_map_changed, - multiMap: f.multichoice_map_changed; - - I18nString optionD = new I18nString("David", ["sk": "Dávid"]) - I18nString optionE = new I18nString("Eve", ["sk": "Eva"]) - I18nString optionF = new I18nString("Felix", ["sk": "Félix"]) - - change enumMap options { - [ - "david": optionD, - "eve": optionE, - "felix": optionF - ] - } - - change enumMap value { - "eve" - } - - change multiMap options { - [ - "david": optionD, - "eve": optionE, - "felix": optionF - ] - } - - change multiMap value { - ["eve", "felix"] as Set - } - - - - + + t4_flex + + + testActionTrigger + + editable + + + t4set + + + + + + + + + - + \ No newline at end of file diff --git a/src/test/resources/application-test-ldap.properties b/src/test/resources/application-test-ldap.properties index 9e04babe626..a2695df7970 100644 --- a/src/test/resources/application-test-ldap.properties +++ b/src/test/resources/application-test-ldap.properties @@ -8,7 +8,7 @@ spring.data.mongodb.drop=true # Elasticsearch spring.data.elasticsearch.drop=true -spring.data.elasticsearch.index.petriNet=${DATABASE_NAME:nae}_dev_test_petrinet +spring.data.elasticsearch.index.petriNet=${DATABASE_NAME:nae}_test_petrinet spring.data.elasticsearch.index.case=${DATABASE_NAME:nae}_test_case spring.data.elasticsearch.index.task=${DATABASE_NAME:nae}_test_task spring.data.elasticsearch.reindex=0 0 0 * * * @@ -56,7 +56,7 @@ logging.level.com.netgrif.application.engine.petrinet.domain.dataset.logic.actio logging.level.com.netgrif.application.engine.admin.AdminConsoleRunner=debug logging.level.com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ExpressionRunner=debug -nae.actions.imports=org.bson.types.ObjectId,com.netgrif.application.engine.petrinet.domain.version.Version,com.netgrif.application.engine.petrinet.domain.PetriNet,com.netgrif.application.engine.petrinet.domain.I18nString,com.netgrif.application.engine.workflow.web.responsebodies.DataSet +nae.actions.imports=org.bson.types.ObjectId,com.netgrif.application.engine.petrinet.domain.version.Version,com.netgrif.application.engine.petrinet.domain.Process,com.netgrif.application.engine.petrinet.domain.I18nString,com.netgrif.application.engine.workflow.web.responsebodies.DataSet nae.actions.star-imports=java.time,com.netgrif.application.engine.petrinet.domain.dataset,com.netgrif.application.engine.petrinet.domain,com.netgrif.application.engine.auth.domain nae.actions.static-star-imports=java.time.LocalDate diff --git a/src/test/resources/application-test-transaction.properties b/src/test/resources/application-test-transaction.properties new file mode 100644 index 00000000000..1f08f62e173 --- /dev/null +++ b/src/test/resources/application-test-transaction.properties @@ -0,0 +1,6 @@ +# Transactions for API +nae.transaction.create-case-transactional=false +nae.transaction.delete-case-transactional=false +nae.transaction.get-data-transactional=false +nae.transaction.set-data-transactional=false +nae.transaction.task-event-transactional=false \ No newline at end of file diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties index 30bdd2a714b..8970b3ab063 100644 --- a/src/test/resources/application-test.properties +++ b/src/test/resources/application-test.properties @@ -20,6 +20,9 @@ nae.security.limits.login-timeout-unit=seconds # Storage nae.storage.clean=true +# Rule engine +rule-engine.enabled=true + nae.admin.password=password @@ -56,12 +59,12 @@ logging.level.com.netgrif.application.engine.petrinet.domain.dataset.logic.actio logging.level.com.netgrif.application.engine.admin.AdminConsoleRunner=debug logging.level.com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ExpressionRunner=debug -nae.actions.imports=org.bson.types.ObjectId,com.netgrif.application.engine.petrinet.domain.version.Version,com.netgrif.application.engine.petrinet.domain.PetriNet,com.netgrif.application.engine.petrinet.domain.I18nString,com.netgrif.application.engine.workflow.web.responsebodies.DataSet +nae.actions.imports=org.bson.types.ObjectId,com.netgrif.application.engine.petrinet.domain.version.Version,com.netgrif.application.engine.petrinet.domain.Process,com.netgrif.application.engine.petrinet.domain.I18nString,com.netgrif.application.engine.workflow.web.responsebodies.DataSet nae.actions.star-imports=java.time,com.netgrif.application.engine.petrinet.domain.dataset,com.netgrif.application.engine.petrinet.domain,com.netgrif.application.engine.auth.domain nae.actions.static-star-imports=java.time.LocalDate nae.ldap.enabled=false -nae.validation.setData.enable:true +nae.validation.setData.enable=true # case field expression runner expressions.runner.cache-size=200 diff --git a/src/test/resources/arc_order_test.xml b/src/test/resources/arc_order_test.xml index 27d9be69bb2..fa74bbbeafe 100644 --- a/src/test/resources/arc_order_test.xml +++ b/src/test/resources/arc_order_test.xml @@ -1,38 +1,43 @@ - - - arc_order_test.xml - TST + + arc_order_test + 1.0.0 Test - + false + false + + TST + + + + + rola1 + Rola 1 + - 1 + t1 0 0 - + t1 - - 2 + p2 0 0 - - - 7 - reset - 2 - 1 + a3 + regular + p2 + t1 1 - 3 - regular - 2 - 1 + a7 + reset + p2 + t1 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/arc_reference_invalid_test.xml b/src/test/resources/arc_reference_invalid_test.xml index 85ade008524..1ff8458ae7c 100644 --- a/src/test/resources/arc_reference_invalid_test.xml +++ b/src/test/resources/arc_reference_invalid_test.xml @@ -1,32 +1,31 @@ - - - + arc_ref_invalid_test - ARi + 1.0.0 Arc ref invalid test + false + false + + ARi + + + - 1 + t1 0 0 - + t1 - - 2 + p2 0 0 - - - 7 + a7 reset - 2 - 1 - 1 - 3 + p2 + t1 + p3 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/arc_reference_test.xml b/src/test/resources/arc_reference_test.xml index 63a241b6724..e118c70eb79 100644 --- a/src/test/resources/arc_reference_test.xml +++ b/src/test/resources/arc_reference_test.xml @@ -1,32 +1,35 @@ - - + arc_ref_test - ART + 1.0.0 Arc ref test - + false + false + + ART + + + - 1 + t1 0 0 - + 1 - - 2 + p2 0 0 - - - 7 + a7 reset - 2 - 1 - 1 - 2 + p2 + t1 + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/assignRoleMainNet_test_.xml b/src/test/resources/assignRoleMainNet_test_.xml index 8c5bbd271df..375ec27f9c7 100644 --- a/src/test/resources/assignRoleMainNet_test_.xml +++ b/src/test/resources/assignRoleMainNet_test_.xml @@ -1,24 +1,28 @@ - - + main - ORG + 1.0.0 main business false - + false + + ORG + Nová organizácia - + + admin_main admin_main - 1 + admin_main_assign - + + + ]]> + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/assignRoleSecondaryNet_test.xml b/src/test/resources/assignRoleSecondaryNet_test.xml index f81db9ed386..10cec245bf3 100644 --- a/src/test/resources/assignRoleSecondaryNet_test.xml +++ b/src/test/resources/assignRoleSecondaryNet_test.xml @@ -1,17 +1,18 @@ - - + secondary - ORG + 1.0.0 secondary business false - - + false + + ORG + Nová organizácia - + + admin_secondary admin_secondary - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/assign_cancel_finish_with_Case_test.xml b/src/test/resources/assign_cancel_finish_with_Case_test.xml index fade333fb77..62657915016 100644 --- a/src/test/resources/assign_cancel_finish_with_Case_test.xml +++ b/src/test/resources/assign_cancel_finish_with_Case_test.xml @@ -1,10 +1,14 @@ - - + assign_cancel_finish_with_Case_net - TST + 1.0.0 Test false + false + + TST + + + field Field @@ -14,18 +18,19 @@ task 0 0 - + Task - 1 + task_assign - + + + ]]> + @@ -33,17 +38,16 @@ task2 0 0 - + Task2 - 1 + task2_finish - - - field: f.field; + + - + ]]> + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/autotrigger_taskref.xml b/src/test/resources/autotrigger_taskref.xml index 649614c347d..717cc7d278b 100644 --- a/src/test/resources/autotrigger_taskref.xml +++ b/src/test/resources/autotrigger_taskref.xml @@ -1,74 +1,61 @@ - - + Praca - PRC + 1.0.0 Práca true - false - - - - - + false + + PRC + tema - + <init>t2</init> </data> - <!-- I18NS --> - <!-- TRANSITIONS --> <transition> <id>t1</id> <x>300</x> <y>60</y> - <layout> - <offset>0</offset> - </layout> - <label>Téma</label> + <title>Téma + + t1_flex + t2 100 140 - - 0 - - + Init + + t2_flex + t2_finish - - - tema: f.tema; - + + + ]]> - p1 20 140 - 1 - false p2 180 140 - 0 - false - a1 regular @@ -83,4 +70,4 @@ p2 1 - + \ No newline at end of file diff --git a/src/test/resources/button_set_data_test.xml b/src/test/resources/button_set_data_test.xml index 924b3649250..d8093f75225 100644 --- a/src/test/resources/button_set_data_test.xml +++ b/src/test/resources/button_set_data_test.xml @@ -1,57 +1,76 @@ - + button_set_data - SDB + 1.0.0 Set Data Button v3 device_hub true true - false - - child_case_id - - <event type="get"> - <id>ref</id> - <actions phase="pre"> - <action> - child_case_id: f.child_case_id; - - if (!child_case_id.value) { - def childCase = createCase("button_set_data", "Child button set data case") - change child_case_id value { childCase.stringId } - } - </action> - </actions> - </event> - </data> + <properties> + <property key="initials">SDB</property> + </properties> + <processEvents/> + <caseEvents/> <data type="button"> <id>button_0</id> <title/> <placeholder>Set Data</placeholder> - <action trigger="set"> - txt: f.text_0; - - change txt value { "Clicked 0!" } - </action> + <event type="set"> + <id>button_0_set</id> + <actions phase="post"> + <action id="action_1"> + <![CDATA[ + change text_0 value { "Clicked 0!" } + ]]> + </action> + </actions> + </event> </data> <data type="button"> <id>button_1</id> <title/> <placeholder>Set Data</placeholder> - <action trigger="set"> - txt: f.text_1; - - change txt value { "Clicked 1!" } - </action> + <event type="set"> + <id>button_1_set</id> + <actions phase="post"> + <action id="action_2"> + <![CDATA[ + change text_1 value { "Clicked 1!" } + ]]> + </action> + </actions> + </event> </data> <data type="button"> <id>button_2</id> <title/> <placeholder>Set Data</placeholder> - <action trigger="set"> - txt: f.text_2; - - change txt value { "Clicked 2!" } - </action> + <event type="set"> + <id>button_2_set</id> + <actions phase="post"> + <action id="action_3"> + <![CDATA[ + change text_2 value { "Clicked 2!" } + ]]> + </action> + </actions> + </event> + </data> + <data type="text"> + <id>child_case_id</id> + <title/> + <event type="get"> + <id>ref</id> + <actions phase="pre"> + <action id="action_0"> + <![CDATA[ + if (!child_case_id.value) { + def childCase = createCase("button_set_data", "Child button set data case") + change child_case_id value { childCase.stringId } + } + ]]> + </action> + </actions> + </event> </data> <data type="text"> <id>text_0</id> @@ -69,93 +88,115 @@ <id>t1</id> <x>300</x> <y>140</y> - <label>task</label> - <dataGroup> - <id>t1</id> - <cols>4</cols> - <layout>legacy</layout> - <dataRef> - <id>child_case_id</id> - <logic> - <behavior>hidden</behavior> - </logic> - </dataRef> - <dataRef> - <id>button_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>text_0</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>button_1</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>text_1</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>button_2</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>text_2</id> - <logic> - <behavior>visible</behavior> - </logic> - <layout> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> + <title>task + + t1_flex + + + child_case_id + + hidden + + + + 0 + 0 + 1 + + + + + button_0 + + editable + + + + 0 + 0 + 1 + + + + + text_0 + + visible + + + + 0 + 0 + 1 + + + + + button_1 + + editable + + + + 0 + 0 + 1 + + + + + text_1 + + visible + + + + 0 + 0 + 1 + + + + + button_2 + + editable + + + + 0 + 0 + 1 + + + + + text_2 + + visible + + + + 0 + 0 + 1 + + + ref - - child_case_id: f.child_case_id; - + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/case_choices_test.xml b/src/test/resources/case_choices_test.xml index f9fe811a3f1..81bd552fce3 100644 --- a/src/test/resources/case_choices_test.xml +++ b/src/test/resources/case_choices_test.xml @@ -1,53 +1,64 @@ - - + test - TST + 1.0.0 Test true - - enum - Enum - Choice 1 - Choice 2 - Choice 3 - + false + + TST + bool Switch - - - enume: f.enum, - check: f.this; - change enume choices { - if (check.rawValue) { - return ["Choice 1","Choice 2","Choice 3"] - } - return ["Choice A","Choice B","Choice C"] - } - - + + bool_set + + + + + + + + + enumeration + Enum + + + + + - - 1 + t1 1 1 - - - 1 - - bool - - editable - - - - enum - - editable - - - + Tran + + t1_flex + + + bool + + editable + + + + + + enumeration + + editable + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/case_name_change_test.xml b/src/test/resources/case_name_change_test.xml index d204b49b11e..cb07f5b198b 100644 --- a/src/test/resources/case_name_change_test.xml +++ b/src/test/resources/case_name_change_test.xml @@ -1,54 +1,77 @@ - + case_name_change_test - CNC + 1.0.0 Case name change Test device_hub true true - false + + CNC + + + bln - <action trigger="set"> - changeCaseProperty "title" about { "Set action title" } - </action> + <event type="set"> + <id>bln_set</id> + <actions phase="post"> + <action id="action_0"> + <![CDATA[ + changeCaseProperty "title" about { "Set action title" } + ]]> + </action> + </actions> + </event> </data> <transition> <id>t1</id> <x>580</x> <y>100</y> - <label>Transition 1</label> - <dataGroup> - <id>t1</id> - <layout>legacy</layout> - <dataRef> - <id>bln</id> - <logic> - <behavior>editable</behavior> - </logic> - </dataRef> - </dataGroup> + <title>Transition 1 + + t1_flex + + + bln + + editable + + + + 0 + 0 + 1 + + + test_event0 - + + test_event2 - + + - + test_event4 - + + @@ -57,29 +80,26 @@ t2 580 220 - + Transition 2 t3 900 100 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/case_search_test.xml b/src/test/resources/case_search_test.xml index 86c2e06ffec..2156cfc08b9 100644 --- a/src/test/resources/case_search_test.xml +++ b/src/test/resources/case_search_test.xml @@ -1,73 +1,85 @@ - - case_search_test.xml - TST + + case_search_test + 1.0.0 Test true - 1 + data_1 1 - 2 + data_2 2 - 3 + data_3 3 - 4 + data_4 date - 5 + data_5 enumeration + + + + + + VALUE1 - VALUE1 - VALUE2 - VALUE3 - VALUE4 tran 0 0 - - - 1 - - 1 - - editable - - - - 2 - - editable - - - - 3 - - editable - - - - 4 - - editable - - - - 5 - - editable - - - + tran + + tran_grid + + + data_1 + + editable + + + + + + data_2 + + editable + + + + + + data_3 + + editable + + + + + + data_4 + + editable + + + + + + data_5 + + editable + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/caseref_test.xml b/src/test/resources/caseref_test.xml deleted file mode 100644 index cc558f0a17b..00000000000 --- a/src/test/resources/caseref_test.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - caseref_test.xml - TST - Test - - - 1 - Case ref - - 5 - 1 - - - - 2 - Text - Initial value - - - - 1 - 180 - 220 - - 1 - false - - - 8 - 420 - 220 - - 0 - false - - - 2 - 300 - 140 - - 3 - - 1 - - - 1 - - editable - - - - - - 3 - 300 - 220 - - 1 - - 1 - - - 1 - - editable - - - - - - 4 - 300 - 300 - - 2 - - 1 - - - 1 - - editable - - - - - - 5 - regular - 1 - 2 - 1 - - - 6 - regular - 1 - 3 - 1 - - - 7 - regular - 1 - 4 - 1 - - - 9 - regular - 2 - 8 - 1 - - - 10 - regular - 3 - 8 - 1 - - - 11 - regular - 4 - 8 - 1 - - \ No newline at end of file diff --git a/src/test/resources/change_allowed_nets_action_test.xml b/src/test/resources/change_allowed_nets_action_test.xml index c47c34aa97e..7e6bdb2974b 100644 --- a/src/test/resources/change_allowed_nets_action_test.xml +++ b/src/test/resources/change_allowed_nets_action_test.xml @@ -1,11 +1,14 @@ - - + test - TST + 1.0.0 Test true - + false + + TST + + + caseref Caseref @@ -14,45 +17,66 @@ - setVal + setNull Switch - - - caseref: f.caseref; - change caseref allowedNets { return ["hello", "world"]} - - + + setNull_set + + + + + + - setNull + setVal Switch - - - caseref: f.caseref; - change caseref allowedNets { return null} - - + + setVal_set + + + + + + - - 1 + t1 1 1 - - - 1 - - setVal - - editable - - - - setNull - - editable - - - + Tran + + t1_flex + + + setVal + + editable + + + + 0 + 0 + 1 + + + + + setNull + + editable + + + + 0 + 0 + 1 + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/change_behavior_update.xml b/src/test/resources/change_behavior_update.xml index 28a6f08cee4..3774544498c 100644 --- a/src/test/resources/change_behavior_update.xml +++ b/src/test/resources/change_behavior_update.xml @@ -1,213 +1,302 @@ - + new_model - NEW + 1.0.0 New Model device_hub true true - false - - text_0 - Text field 1 - Demo behavior - - - text_1 - Text field 2 - Demo behavior - + + NEW + + + boolean_0 Edit behavior on transition false - - bln: f.this, - txt0: f.text_0, - trans: t.t1; - - make txt0, editable on trans when { bln.rawValue } - make txt0, required on trans when { bln.rawValue } - make txt0, initial on trans when { !bln.rawValue } - + + boolean_0_set + + + + + + boolean_1 Edit behavior on transitions false - - bln: f.this, - txt0: f.text_0; - - make txt0, editable on transitions when { bln.rawValue } - make txt0, required on transitions when { bln.rawValue } - - make txt0, visible on transitions when { !bln.rawValue } - make txt0, optional on transitions when { !bln.rawValue } - + + boolean_1_set + + + + + + boolean_2 Edit behavior on multiple transitions false - - bln: f.this, - txt0: f.text_0, - txt1: f.text_1, - trans: t.t1, - trans2: t.t3; - - make txt0, editable on ([trans, trans2]) when { bln.rawValue } - make txt0, visible on ([trans, trans2]) when { !bln.rawValue } - + + boolean_2_set + + + + + + boolean_3 Edit behavior of multiple fields on multiple transitions false - - bln: f.this, - txt0: f.text_0, - txt1: f.text_1, - trans: t.t1, - trans2: t.t3; - - make [txt0, txt1], editable on ([trans, trans2]) when { bln.rawValue } - make [txt0, txt1], visible on ([trans, trans2]) when { !bln.rawValue } - + + boolean_3_set + + + + + + + + + text_0 + Text field 1 + Demo behavior + + + text_1 + Text field 2 + Demo behavior t1 340 140 - + Test transition auto - - t1_0 - legacy - - text_0 - - visible - optional - - - - text_1 - - visible - - - - boolean_0 - - editable - - - - boolean_1 - - editable - - - - boolean_2 - - editable - - - - boolean_3 - - editable - - - + + t1_flex + + + text_0 + + visible + + + + 0 + 0 + 1 + + + + + text_1 + + visible + + + + 0 + 0 + 1 + + + + + boolean_0 + + editable + + + + 0 + 0 + 1 + + + + + boolean_1 + + editable + + + + 0 + 0 + 1 + + + + + boolean_2 + + editable + + + + 0 + 0 + 1 + + + + + boolean_3 + + editable + + + + 0 + 0 + 1 + + + - t3 + t2 740 140 - - - group_1 - legacy - - text_0 - - visible - - - - text_1 - - visible - - - + Test multiple transitions 3 + + t2_flex + + + text_0 + + visible + + + + 0 + 0 + 1 + + + + + text_1 + + visible + + + + 0 + 0 + 1 + + + - t4 + t3 740 140 - - - group_1 - legacy - - text_0 - - visible - - - - text_1 - - visible - - - + Test multiple transitions 1 + + t3_flex + + + text_0 + + visible + + + + 0 + 0 + 1 + + + + + text_1 + + visible + + + + 0 + 0 + 1 + + + - t2 + t4 740 140 - - - group_1 - legacy - - text_0 - - visible - - - - - group_2 - legacy - - text_1 - - visible - - - + Test multiple transitions 2 + + t4_flex + + + text_0 + + visible + + + + 0 + 0 + 1 + + + + + text_1 + + visible + + + + 0 + 0 + 1 + + + p1 540 140 - + step 0 - false p2 100 140 - + init 1 - false a1 @@ -230,4 +319,4 @@ t1 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/change_caseref_value_action_test.xml b/src/test/resources/change_caseref_value_action_test.xml index b69f6c46019..d548afcee6d 100644 --- a/src/test/resources/change_caseref_value_action_test.xml +++ b/src/test/resources/change_caseref_value_action_test.xml @@ -1,78 +1,100 @@ - - + change_value - TST + 1.0.0 Test true - - - caseref - Caseref - - change_value - - + false + + TST + + + addExisting Switch - - - caseref: f.caseref; - change caseref value {return [useCase.stringId]} - - + + addExisting_set + + + + + + - addNew + addInvalidNet Switch - - - caseref: f.caseref; - def newCase = createCase("change_value") - change caseref value {return caseref.rawValue + [newCase.stringId]} - - + + addInvalidNet_set + + + + + + - addInvalidNet + addNew Switch - - - caseref: f.caseref; - def newCase = createCase("test"); - try { - change caseref value {return caseref.rawValue + [newCase.stringId]} - } catch (IllegalArgumentException e) {} - - + + addNew_set + + + + + + + + + caseref + Caseref + + change_value + - - 1 + t1 1 1 - - - 1 - - addExisting - - editable - - - - addNew - - editable - - - - addNew - - editable - - - + Tran + + t1_flex + + + addExisting + + editable + + + + 0 + 0 + 1 + + + + + addNew + + editable + + + + 0 + 0 + 1 + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/constructor_destructor.xml b/src/test/resources/constructor_destructor.xml index 043e2907219..e95471bb5b7 100644 --- a/src/test/resources/constructor_destructor.xml +++ b/src/test/resources/constructor_destructor.xml @@ -1,38 +1,29 @@ - - + constructor_destructor - CAD + 1.0.0 Constructor and Destructor business false - - - - process_role - Process role - - - text - Text - text - - + false + + CAD + process_role - + true false - + - upload - + + + ]]> + @@ -40,21 +31,31 @@ create - - text: f.text; - - change text value {return "Its working..."} - + + + pdf - + + + ]]> + - - + + process_role + Process role + + + text + Text + text + + \ No newline at end of file diff --git a/src/test/resources/create_case_failure.xml b/src/test/resources/create_case_failure.xml new file mode 100644 index 00000000000..b599e6f0691 --- /dev/null +++ b/src/test/resources/create_case_failure.xml @@ -0,0 +1,31 @@ + + create_case_failure + 1.0.0 + Test + false + false + + TST + + + + + x123 + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/create_case_locale.xml b/src/test/resources/create_case_locale.xml index 99fe3759b8a..bedfdee0cfd 100644 --- a/src/test/resources/create_case_locale.xml +++ b/src/test/resources/create_case_locale.xml @@ -1,16 +1,16 @@ - - currency_test.xml - TST + + create_case_locale + 1.0.0 Test - Slovenský preklad + Slovenský preklad - English translation + English translation - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/currency_test.xml b/src/test/resources/currency_test.xml deleted file mode 100644 index 1fdf059b642..00000000000 --- a/src/test/resources/currency_test.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - currency_test.xml - TST - Test - - - - number - Number - - - - EUR - - 3 - - sk_SK - - - - - - - \ No newline at end of file diff --git a/src/test/resources/data_button_test.xml b/src/test/resources/data_button_test.xml index 8d929164844..b9587f1e5e7 100644 --- a/src/test/resources/data_button_test.xml +++ b/src/test/resources/data_button_test.xml @@ -1,66 +1,97 @@ - - + test - TST + 1.0.0 Test true - - + false + + TST + + + btn1 button Button title Button field description - - - sequence: f.num; - change sequence value { sequence.value + 1 } - - + + btn1_set + + + + + + btn2 button Button title Button field description - - - sequence: f.num; - change sequence value { sequence.value + 1 } - - + + btn2_set + + + + + + num number 0 - task 0 0 - - - btn1 - - editable - - - - btn2 - - visible - - - - num - - visible - - + task + + task_flex + + + btn1 + + editable + + + + 0 + 0 + 1 + + + + + btn2 + + visible + + + + 0 + 0 + 1 + + + + + num + + visible + + + + 0 + 0 + 1 + + + - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/data_map.xml b/src/test/resources/data_map.xml index cb947645633..1c01be203cd 100644 --- a/src/test/resources/data_map.xml +++ b/src/test/resources/data_map.xml @@ -1,30 +1,30 @@ - - + test - TST - Test + 1.0.0 + Test true - + false + + TST + enumeration - Enumeration map + Enumeration map - - - + + + second - - Prvá možnosť - Druhá možnosť - Tretia možnosť + Prvá možnosť + Druhá možnosť + Tretia možnosť - Erste Option - Zweite Option - Dritte Option + Erste Option + Zweite Option + Dritte Option - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/data_map_2.xml b/src/test/resources/data_map_2.xml index e415c4e3e28..3f83bbe42ab 100644 --- a/src/test/resources/data_map_2.xml +++ b/src/test/resources/data_map_2.xml @@ -1,33 +1,30 @@ - - + test - TST + 1.0.0 Test true - + false + + TST + multichoice Multichoice map - - - + + + - - second - first - + ["first", "second"] - - Prvá možnosť - Druhá možnosť - Tretia možnosť + Prvá možnosť + Druhá možnosť + Tretia možnosť - Erste Option - Zweite Option - Dritte Option + Erste Option + Zweite Option + Dritte Option - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/data_service_referenced.xml b/src/test/resources/data_service_referenced.xml index ce077430b8d..35f1be7e395 100644 --- a/src/test/resources/data_service_referenced.xml +++ b/src/test/resources/data_service_referenced.xml @@ -1,48 +1,65 @@ - - + referenced 1.0.0 - RFD Referenced true - false - - - + false + + RFD + file File - - res: f.result; - change res value { - return "OK"; - } - + + file_set + + + + + + result Result - - 1 + t1 546 177 - - - file - - editable - - - - result - - editable - - + Transition + + t1_flex + + + file + + editable + + + + 0 + 0 + 1 + + + + + result + + editable + + + + 0 + 0 + 1 + + + - - - + \ No newline at end of file diff --git a/src/test/resources/data_service_taskref.xml b/src/test/resources/data_service_taskref.xml index 071cef8ced8..47656794f35 100644 --- a/src/test/resources/data_service_taskref.xml +++ b/src/test/resources/data_service_taskref.xml @@ -1,46 +1,52 @@ - - + refering 1.0.0 - REF Refering true - false - - - + false + + REF + + + ref - + </data> - <!-- TRANSITIONS --> <transition> - <id>1</id> + <id>t1</id> <x>546</x> <y>177</y> - <label>Transition</label> + <title>Transition + + t1_flex + + + ref + + editable + + + + 0 + 0 + 1 + + + - 1 + t1_assign - - taskref: f.ref; - + + + ]]> + - - ref - - editable - - - - - + \ No newline at end of file diff --git a/src/test/resources/data_test.xml b/src/test/resources/data_test.xml index a9e4feb8786..516d856a0d2 100644 --- a/src/test/resources/data_test.xml +++ b/src/test/resources/data_test.xml @@ -1,272 +1,397 @@ - - - 1 - TES + + data_test + 1.0.0 Data test true - - - number - Number - Number field placeholder - Number field description - inrange 0,inf - - - inrange 0,inf - Number field validation message - - - 10 - - - - text - Text - Text field placeholder - Text field description - email - - - email - Mail validation message - - - text - - - - enumeration - Enumeration - Enumeration field placeholder - Enumeration field description - enumeration - enumeration2 - enumeration3 - enumeration - - - - multichoice - Multichoice - Multichoice field placeholder - Multichoice field description - multichoice - multichoice2 - multichoice3 - multichoice, multichoice2 - - - - emptyMultichoice - empty multichoice - - + false + + TES + + + boolean Boolean Boolean field placeholder Boolean field description - requiredTrue - requiredTrue + requiredTrue Boolean field validation message true - + + caseRef + CaseRef + + processId1 + processId2 + + date Date Date field placeholder Date field description - between today,future - between today,future + between + + today + future + Date field validation message - between today,tommorow + between + + today + tommorow + Date field validation message 2 - - - file - File - File field placeholder - File field description - - - - user - User - User field placeholder - User field description - - dateTime DateTime DateTime field placeholder DateTime field description - between today,future - between today,future + between + + today + future + Date field validation message - between today,future + between + + today + future + Date field validation message 2 - - - caseRef - CaseRef - - processId1 - processId2 - + + emptyMultichoice + empty multichoice + + + emptyMultichoiceMap + Empty multichoice map + Multichoice map placeholder + Multichoice map description + + + emptyTaskRef + Empty task ref - emptyUserList Empty user list User list description - - - emptyTaskRef - Empty task ref + + enumeration + Enumeration + Enumeration field placeholder + Enumeration field description + + + + + + enumeration - - - emptyMultichoiceMap - Empty multichoice map - Multichoice map description - Multichoice map placeholder + + file + File + File field placeholder + File field description - i18n Text I18n Text I18n field This is I18n text field - Default i18n text value - translationRequired sk,en + translationRequired + + sk + en + Slovak and English language required - translationOnly sk,en,cz,de + translationOnly + + sk + en + cz + de + Only Slovak, English, Czech and German languages allowed + Default i18n text value + + + multichoice + Multichoice + Multichoice field placeholder + Multichoice field description + + + + + + multichoice,multichoice2 + + + number + Number + Number field placeholder + Number field description + + + inrange + + 0 + inf + + Number field validation message + + + 10 + + + text + Text + Text field placeholder + Text field description + + + email + Mail validation message + + + text + + + user + User + User field placeholder + User field description - - - 1 + t1 1 1 - - - number - - editable - - - - text - - editable - - - - enumeration - - editable - - - - multichoice - - editable - - - - boolean - - editable - - - - date - - editable - - - - file - - editable - - - - user - - editable - - - - dateTime - - editable - - - - caseRef - - editable - - - - emptyUserList - - editable - - - - emptyMultichoice - - editable - - - - emptyTaskRef - - editable - - - - emptyMultichoiceMap - - editable - - - - i18n - - editable - - + Transition + + t1_flex + + + number + + editable + + + + 0 + 0 + 1 + + + + + text + + editable + + + + 0 + 0 + 1 + + + + + enumeration + + editable + + + + 0 + 0 + 1 + + + + + multichoice + + editable + + + + 0 + 0 + 1 + + + + + boolean + + editable + + + + 0 + 0 + 1 + + + + + date + + editable + + + + 0 + 0 + 1 + + + + + file + + editable + + + + 0 + 0 + 1 + + + + + user + + editable + + + + 0 + 0 + 1 + + + + + dateTime + + editable + + + + 0 + 0 + 1 + + + + + caseRef + + editable + + + + 0 + 0 + 1 + + + + + emptyUserList + + editable + + + + 0 + 0 + 1 + + + + + emptyMultichoice + + editable + + + + 0 + 0 + 1 + + + + + emptyTaskRef + + editable + + + + 0 + 0 + 1 + + + + + emptyMultichoiceMap + + editable + + + + 0 + 0 + 1 + + + + + i18n + + editable + + + + 0 + 0 + 1 + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/data_text_validation.xml b/src/test/resources/data_text_validation.xml deleted file mode 100644 index 2c9f5a9d082..00000000000 --- a/src/test/resources/data_text_validation.xml +++ /dev/null @@ -1,268 +0,0 @@ -F - - test - TST - Test - true - - - numberOdd - Number - 10 - Number field description - Number field placeholder - - - odd - Number field validation message odd - - - - - - numberEven - Number - 1 - Number field description - Number field placeholder - - - even - Number field validation message even - - - - - numberPos - Number - -10 - Number field description - Number field placeholder - - - positive - Number field validation message positive - - - - - numberNeg - Number - 10 - Number field description - Number field placeholder - - - negative - Number field validation message negative - - - - - numberDec - Number - 10.1 - Number field description - Number field placeholder - - - decimal - Number field validation message decimal - - - - - number0Inf - Number - -10 - Number field description - Number field placeholder - - - inrange 0,inf - Number field validation message 0-inf - - - - - numberInf0 - Number - 10 - Number field description - Number field placeholder - - - inrange inf,0 - Number field validation message inf-0 - - - - - numberTest - Number - -1 - Number field description - Number field placeholder - - - even - Number field validation message even - - - inrange inf,0 - Number field validation message inf-0 - - - - - - text - Text - text - Text field description - Text field placeholder - - - email - Mail validation message - - - - - length5 - Text - texttext - Text field description - Text field placeholder - - - length 5 - length validation message - - - - - telnum - Text - text - Text field description - Text field placeholder - - - telNumber - telNumber validation message - - - - - - date - Date - Date field description - Date field placeholder - - - between today,future - Date field validation message - - - - - datepast - Date - Date field description - Date field placeholder - - - between past,today - Date field validation message - - - - - - 1 - 1 - 1 - - - numberOdd - - editable - - - - numberEven - - editable - - - - numberPos - - editable - - - - numberNeg - - editable - - - - numberDec - - editable - - - - numberInf0 - - editable - - - - number0Inf - - editable - - - - numberTest - - editable - - - - length5 - - editable - - - - telnum - - editable - - - - date - - editable - - - - datepast - - editable - - - - text - - editable - - - - \ No newline at end of file diff --git a/src/test/resources/datagroup_no_id_test.xml b/src/test/resources/datagroup_no_id_test.xml deleted file mode 100644 index e97b245cfbc..00000000000 --- a/src/test/resources/datagroup_no_id_test.xml +++ /dev/null @@ -1,57 +0,0 @@ - - Entity1 - 1.0.0 - ENT - Entity1 - true - - variable1 - Attribute1 - - - variable2 - Attribute2 - - - test - 100 - 20 - - \ No newline at end of file diff --git a/src/test/resources/datagroup_test.xml b/src/test/resources/datagroup_test.xml index ab041058138..3cc64d33719 100644 --- a/src/test/resources/datagroup_test.xml +++ b/src/test/resources/datagroup_test.xml @@ -1,133 +1,162 @@ - - + test - TST + 1.0.0 Test - + false + false + + TST + + + role1 + Agent + + + role2 + Premium + - 1 + data1 Field 1 10 - 2 + data2 Field 2 - 3 + data3 Field 3 - 4 + data4 Field 4 - 5 + data5 Field 5 - 6 + data6 Field 6 - - - 1 - Agent - - - 2 - Premium - - + + t1 + 362 + 183 + Test data groups + + role1 + + true + + + + t1_flex + + + data1 + + editable + + + + 0 + 0 + 1 + + + + + data2 + + editable + + + + 0 + 0 + 1 + + + + + data3 + + editable + + + + 0 + 0 + 1 + + + + + data4 + + editable + + + + 0 + 0 + 1 + + + + + data5 + + editable + + + + 0 + 0 + 1 + + + + + data6 + + editable + + + + 0 + 0 + 1 + + + + - 2 + p2 274 187 - 1 - false - 3 + p3 506 186 - 0 - false - - - 1 - 362 - 183 - - - 1 - - true - - - - - 1 - Left - start - - 1 - - visible - - - - 2 - - visible - - - - 3 - - visible - - - - - 2 - Right - end - - 4 - - visible - - - - 5 - - visible - - - - 6 - - visible - - - - - - 4 + a4 regular - 2 - 1 + p2 + t1 1 - 5 + a5 regular - 1 - 3 + t1 + p3 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/datagroup_test_layout.xml b/src/test/resources/datagroup_test_layout.xml deleted file mode 100644 index 4e5a0b25667..00000000000 --- a/src/test/resources/datagroup_test_layout.xml +++ /dev/null @@ -1,587 +0,0 @@ - - - datagroup_test - DGT - Data group test - true - false - - - - newRole_1 - - - - - - - text_0 - Text root top 1 - - - text_1 - Text root top 2 - - - taskRefCols3 - - - - text_2 - Text root mid 1-1 - - - button_0 - - Ref 3 cols - - - text_3 - Text root mid 1-2 - - - button_1 - - Ref 5 cols - - - taskRefCols5 - - - - text_4 - Text root mid 2-1 - - - text_5 - Text root mid 2-2 - - - text_6 - Text root bot 2 - - - button_2 - - Ref nested - - - taskRefNested - - - - text_7 - Text root bot 1 - - - text_8 - 3 cols 1 - - - text_9 - 3 cols 2 - - - text_10 - 5 cols 1 - - - text_11 - 5 cols 2 - - - text_12 - Nested top - - - text_13 - Nested bot - - - taskRefChild - - t5 - - - text_14 - Child top - - - number_0 - Child bot - - - file - File - - - - - t1 - 508 - 400 - - 0 - 4 - - - - DataGroup1 - grid - - text_0 - - editable - - - 3 - 0 - 1 - 1 - 0 - - outline - - - - text_1 - - editable - - - 0 - 2 - 1 - 2 - 0 - - outline - - - - button_0 - - editable - taskRefCols3: f.taskRefCols3; - - def task = findTask({ it.transitionId.eq("t2") & it.caseId.eq(useCase.stringId) }); - - change taskRefCols3 value { return [task.stringId]; } - - - - 3 - 2 - 1 - 1 - 0 - - outline - - - - taskRefCols3 - - editable - - - 0 - 3 - 1 - 4 - 0 - - outline - - - - text_2 - - editable - - - 3 - 4 - 1 - 1 - 0 - - outline - - - - text_3 - - editable - - - 0 - 6 - 1 - 2 - 0 - - outline - - - - button_1 - - editable - taskRefCols5: f.taskRefCols5; - - def task = findTask({ it.transitionId.eq("t3") & it.caseId.eq(useCase.stringId) }); - - change taskRefCols5 value { return [task.stringId]; } - - - - 3 - 6 - 1 - 1 - 0 - - outline - - - - taskRefCols5 - - editable - - - 0 - 7 - 1 - 4 - 0 - - outline - - - - text_4 - - editable - - - 3 - 8 - 1 - 1 - 0 - - outline - - - - text_5 - - editable - - - 0 - 10 - 1 - 2 - 0 - - outline - - - - button_2 - - editable - taskRefNested: f.taskRefNested; - - def task = findTask({ it.transitionId.eq("t4") & it.caseId.eq(useCase.stringId) }); - - change taskRefNested value { return [task.stringId]; } - - - - 3 - 10 - 1 - 1 - 0 - - outline - - - - taskRefNested - - editable - - - 0 - 11 - 1 - 4 - 0 - - outline - - - - text_6 - - editable - - - 3 - 12 - 1 - 1 - 0 - - outline - - - - text_7 - - editable - - - 0 - 14 - 1 - 2 - 0 - - outline - - - - - finishevent - - - generatePdf("t1","file"); - - - - - - t2 - 689 - 375 - - 0 - 3 - - - - newRole_1 - - true - - - - DataGroup2 - grid - 3 - - text_8 - - editable - - - 2 - 0 - 1 - 1 - 0 - - outline - - - - text_9 - - editable - - - 0 - 2 - 1 - 1 - 0 - - outline - - - - - - t3 - 700 - 498 - - 0 - 5 - - - - newRole_1 - - true - - - - DataGroup3 - grid - 5 - - text_10 - - editable - - - 4 - 0 - 1 - 1 - 0 - - outline - - - - text_11 - - editable - - - 0 - 2 - 1 - 3 - 0 - - outline - - - - - - t4 - 700 - 613 - - 0 - - - - newRole_1 - - true - - - - DataGroup4 - grid - - text_12 - - editable - - - 3 - 0 - 1 - 1 - 0 - - outline - - - - text_13 - - editable - - - 0 - 3 - 1 - 2 - 0 - - outline - - - - taskRefChild - - editable - - - 0 - 1 - 1 - 4 - 0 - - outline - - - - - - t5 - 807 - 616 - - 0 - - - - newRole_1 - - true - - - - DataGroup5 - grid - - text_14 - - editable - - - 3 - 0 - 1 - 1 - 0 - - outline - - - - number_0 - - editable - - - 0 - 2 - 1 - 2 - 0 - - outline - - - - - - - diff --git a/src/test/resources/delete_case_failure.xml b/src/test/resources/delete_case_failure.xml new file mode 100644 index 00000000000..b0faedee77d --- /dev/null +++ b/src/test/resources/delete_case_failure.xml @@ -0,0 +1,31 @@ + + delete_case_failure + 1.0.0 + Test + false + false + + TST + + + + + x123 + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/enum_list.xml b/src/test/resources/enum_list.xml deleted file mode 100644 index 808a464f4dd..00000000000 --- a/src/test/resources/enum_list.xml +++ /dev/null @@ -1,146 +0,0 @@ - - - test - TST - Test - true - - - enumeration - Enumeration - Item 1 - Item 2 - Item 3 - Item 4 - Item 5 - Item 6 - Item 7 - Item 8 - Item 9 - Item 10 - Item 5 - - 5 - - - - m1: f.enumeration, - m2: f.enumeration2; - - change m2 value { m1.value } - - - - - enumeration2 - Enumeration 2 - Item 1 - Item 2 - Item 3 - Item 4 - Item 5 - Item 6 - Item 7 - Item 8 - Item 9 - Item 10 - - - - - - multichoice - Multichoice - Item 1 - Item 2 - Item 3 - Item 4 - - 2 - - - - m1: f.multichoice, - m2: f.multichoice2; - - change m2 value { m1.value } - - - - - multichoice2 - Multichoice 2 - Item 1 - Item 2 - Item 3 - Item 4 - - 10 - - - - multichoice3 - Multichoice 3 - Item 1 - Item 2 - Item 3 - Item 4 - - - - task - 0 - 0 - - auto - - task_1 - false - - enumeration - - editable - required - - - - multichoice3 - - editable - required - - - - enumeration2 - - visible - - - - - task_2 - false - - multichoice3 - - editable - required - - - - multichoice - - editable - required - - - - multichoice2 - - visible - - - - - \ No newline at end of file diff --git a/src/test/resources/enumeration_multichoice_options.xml b/src/test/resources/enumeration_multichoice_options.xml index e5ca5d5b9d7..24e0bbddfb2 100644 --- a/src/test/resources/enumeration_multichoice_options.xml +++ b/src/test/resources/enumeration_multichoice_options.xml @@ -1,19 +1,23 @@ - - + enumeration_multichoice_options + 1.0.0 Enumeration/multichoice options - EMO true - + false + + EMO + enumeration Enumeration values - Alice - Bob - Carol + + + + + Bob - enumeration_like_map Enumeration options @@ -24,16 +28,16 @@ Bob - multichoice Multichoice values - Alice - Bob - Carol + + + + + Alice,Bob - multichoice_like_map Multichoice options @@ -44,76 +48,66 @@ Alice,Bob - - 1 + t1 379 273 - + Task - editable auto - - DataGroup_0 - grid - - enumeration - - editable - - - 0 - 0 - 1 - 2 - 0 - - outline - - - - enumeration_like_map - - editable - - - 2 - 0 - 1 - 2 - 0 - - outline - - - - multichoice - - editable - - - 0 - 1 - 1 - 2 - 0 - - outline - - - - multichoice_like_map - - editable - - - 2 - 1 - 1 - 2 - 0 - - outline - - - + + t1_flex + + + enumeration + + editable + + + + 0 + 0 + 1 + + + + + enumeration_like_map + + editable + + + + 0 + 0 + 1 + + + + + multichoice + + editable + + + + 0 + 0 + 1 + + + + + multichoice_like_map + + editable + + + + 0 + 0 + 1 + + + - + \ No newline at end of file diff --git a/src/test/resources/event_test.xml b/src/test/resources/event_test.xml index 0f88be9862a..648eb8bec5b 100644 --- a/src/test/resources/event_test.xml +++ b/src/test/resources/event_test.xml @@ -1,8 +1,7 @@ - + test - TST + 1.0.0 Test task_assign_pre @@ -23,14 +22,18 @@ task_cancel_pre task_cancel_pre - - - field: f.chained; - change field about { - return "chained" - } - - + + task_cancel_pre_set + + + + change chained about { + return "chained" + } + + + + task_cancel_post @@ -44,16 +47,13 @@ task 0 0 - + task task_assign - Prirad - Task assigned - field: f.task_assign_post; - change field about { + change task_assign_post about { return "task_assign_post" } @@ -62,23 +62,21 @@ - field: f.task_assign_pre; - change field about { + change task_assign_pre about { return "task_assign_pre" } + Task assigned + Prirad task_finish - Dokonic - Task finished - field: f.task_finish_post; - change field about { + change task_finish_post about { return "task_finish_post" } @@ -87,24 +85,22 @@ - field: f.task_finish_pre; - change field about { + change task_finish_pre about { return "task_finish_pre" } + Task finished + Dokonic task_cancel - Zrus - Task cancelled - field: f.task_cancel_post; - change field about { - return "task_cancel_post" + change task_cancel_post about { + return "task_cancel_post" } @@ -112,13 +108,14 @@ - field: f.task_cancel_pre; - change field about { - return "task_cancel_pre" + change task_cancel_pre about { + return "task_cancel_pre" } + Task cancelled + Zrus - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/field_view.xml b/src/test/resources/field_view.xml deleted file mode 100644 index 7c4dda54c1b..00000000000 --- a/src/test/resources/field_view.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - test - TST - Test - - - - boo - boo - - - ok - ko - - - - - - 0 - 0 - 0 - - - boo - - editable - - - - - - \ No newline at end of file diff --git a/src/test/resources/file_test.xml b/src/test/resources/file_test.xml index 8bd07b46832..f7cefe05b72 100644 --- a/src/test/resources/file_test.xml +++ b/src/test/resources/file_test.xml @@ -1,64 +1,96 @@ - + test - TST + 1.0.0 Test true - + false + + TST + + + - 1 + data_1 file - - - field: f.2; - change field about { - return "2"; - } - - - - - field: f.3; - change field about { - return "3"; - } - - + + data_1_get + + + + + + + + data_1_set + + + + + + - 2 + data_2 2 - 3 + data_3 3 - tran 0 0 - - - 1 - - 1 - - editable - - - - 2 - - visible - - - - 3 - - visible - - - + tran + + tran_flex + + + data_1 + + editable + + + + 0 + 0 + 1 + + + + + data_2 + + visible + + + + 0 + 0 + 1 + + + + + data_3 + + visible + + + + 0 + 0 + 1 + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/file_test_net.xml b/src/test/resources/file_test_net.xml deleted file mode 100644 index 80ea01e33d1..00000000000 --- a/src/test/resources/file_test_net.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - test - TST - Test - - file_1 - File 1 - - - - file_2 - File 2 - - - - file_3 - File 3 - - - - 2 - 327 - 196 - - auto - - - file_1 - - editable - - - - - file_2 - - editable - - - - - file_3 - - editable - - - - - - 6 - 327 - 250 - - auto - - - file_1 - - visible - - - - - file_2 - - visible - - - - - file_3 - - visible - - - - - - - 1 - 177 - 194 - - 1 - false - - - - 4 - read - 1 - 2 - 1 - - - 7 - read - 1 - 6 - 1 - - \ No newline at end of file diff --git a/src/test/resources/flow.xml b/src/test/resources/flow.xml deleted file mode 100644 index 54540fb0ff9..00000000000 --- a/src/test/resources/flow.xml +++ /dev/null @@ -1,280 +0,0 @@ - - new_model - NEW - New Model - device_hub - true - true - false - - text1 - Text - test text 2 col - - - text2 - Text - test text 2 col - - - - text3 - test text 5 col - test text 5 col - - - text4 - test text 5 col - test text - - - text5 - test text 5 col - test text 5 col - - - text6 - test text 5 col - test text 5 col - - - text7 - test text 5 col - test text 5 col - - - - text8 - test text 3 col - test text 3 col - - - text9 - test text 3 col - test text 3 col - - - text10 - test text 3 col - test text 3 col - - - - text11 - test text 8 col dlhý titleaaaaaaaaaaaaaaaaa - test text 8 col - - - text12 - test text 8 col dlhý titleaaaaaaaaaaaaaaaaa - test text 8 col - - - text13 - test text 8 col dlhý titleaaaaaaaaaaaaaaaaa - test text 8 col - - - text14 - test text 8 col dlhý titleaaaaaaaaaaaaaaaaa - test text 8 col - - - text15 - test text 8 col dlhý titleaaaaaaaaaaaaaaaaa - test text 8 col - - - text16 - test text 8 col dlhý titleaaaaaaaaaaaaaaaaa - test text 8 col - - - text17 - test text 8 col dlhý titleaaaaaaaaaaaaaaaaa - test text 8 col - - - text18 - test text 8 col dlhý titleaaaaaaaaaaaaaaaaa - test text 8 col - - - pdf - pdf - - - t1 - 220 - 100 - - - t2 - 220 - 100 - - diff --git a/src/test/resources/importTest/NoLabel.xml b/src/test/resources/importTest/NoLabel.xml index c2387aa3deb..dd168e7a23e 100644 --- a/src/test/resources/importTest/NoLabel.xml +++ b/src/test/resources/importTest/NoLabel.xml @@ -1,47 +1,59 @@ - - + ImportTest 1.0.0 - imp Import Test true false + + imp + variable1 Attribute1 - - 1 - + t1 0 0 - - dg - legacy - - variable1 - - editable - - - + Test + + t1_flex + + + variable1 + + editable + + + + 0 + 0 + 1 + + + - layout 0 0 - - dg - legacy - - variable1 - - editable - - - + + <flex> + <id>layout_flex</id> + <item> + <dataRef> + <id>variable1</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + </flex> </transition> - -</document> \ No newline at end of file +</process> \ No newline at end of file diff --git a/src/test/resources/importTest/child_extending_parent.xml b/src/test/resources/importTest/child_extending_parent.xml new file mode 100644 index 00000000000..d6553489d71 --- /dev/null +++ b/src/test/resources/importTest/child_extending_parent.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8"?> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> + <id>child_extending_parent</id> + <version>1.0.0</version> + <extends> + <id>parent_to_be_extended</id> + <version>1.1.0</version> + </extends> + <title>Child extending parent + true + false + + + tag2 + + + + role2 + Role 2 + + + + variable2 + Attribute2 + + + + taskref2 + TaskRef2 + t0 + + + + t2 + 0 + 0 + Test + + dg + + + variable1 + + editable + + + + + + + + p2 + 0 + 0 + 1 + + + + a2 + regular + p2 + t2 + 1 + + + + a3 + regular + t1 + p2 + 1 + + + + a4 + regular + t0 + p2 + 1 + + + \ No newline at end of file diff --git a/src/test/resources/importTest/extending_non_existing_parent.xml b/src/test/resources/importTest/extending_non_existing_parent.xml new file mode 100644 index 00000000000..efe18af9516 --- /dev/null +++ b/src/test/resources/importTest/extending_non_existing_parent.xml @@ -0,0 +1,15 @@ + + extending_non_existing_parent + 1.0.0 + + something + 0.0.0 + + Extending non existing parent test net + true + false + + ENP + + \ No newline at end of file diff --git a/src/test/resources/importTest/extending_with_invalid_extension_1.xml b/src/test/resources/importTest/extending_with_invalid_extension_1.xml new file mode 100644 index 00000000000..ccd30cc8eb0 --- /dev/null +++ b/src/test/resources/importTest/extending_with_invalid_extension_1.xml @@ -0,0 +1,15 @@ + + extending_with_invalid_extension_1 + 1.0.0 + + + 1.0.0 + + Extending with invalid extension - empty id + true + false + + EIE + + diff --git a/src/test/resources/importTest/extending_with_invalid_extension_2.xml b/src/test/resources/importTest/extending_with_invalid_extension_2.xml new file mode 100644 index 00000000000..48ebaa71c48 --- /dev/null +++ b/src/test/resources/importTest/extending_with_invalid_extension_2.xml @@ -0,0 +1,15 @@ + + extending_with_invalid_extension_2 + 1.0.0 + + parent_to_be_extended + + + Extending with invalid extension - empty version + true + false + + EIE + + \ No newline at end of file diff --git a/src/test/resources/importTest/extending_with_invalid_extension_3.xml b/src/test/resources/importTest/extending_with_invalid_extension_3.xml new file mode 100644 index 00000000000..d31389e72f1 --- /dev/null +++ b/src/test/resources/importTest/extending_with_invalid_extension_3.xml @@ -0,0 +1,15 @@ + + extending_with_invalid_extension_3 + 1.0.0 + + parent_to_be_extended + 100 + + Extending with invalid extension - wrong version + true + false + + EIE + + \ No newline at end of file diff --git a/src/test/resources/importTest/parent_to_be_extended.xml b/src/test/resources/importTest/parent_to_be_extended.xml new file mode 100644 index 00000000000..7637a1fd189 --- /dev/null +++ b/src/test/resources/importTest/parent_to_be_extended.xml @@ -0,0 +1,61 @@ + + + parent_to_be_extended + 1.0.0 + + super_parent_to_be_extended + 1.0.0 + + Parent test net to be extended + true + false + + + tag1 + + + + role1 + Role 1 + + + + variable1 + Attribute1 + + + + t1 + 0 + 0 + Test + + dg + + + variable1 + + editable + + + + + + + + p1 + 0 + 0 + 1 + + + + a1 + regular + p1 + t1 + 1 + + + \ No newline at end of file diff --git a/src/test/resources/importTest/super_parent_to_be_extended.xml b/src/test/resources/importTest/super_parent_to_be_extended.xml new file mode 100644 index 00000000000..08aac9af310 --- /dev/null +++ b/src/test/resources/importTest/super_parent_to_be_extended.xml @@ -0,0 +1,54 @@ + + + super_parent_to_be_extended + 1.0.0 + Super parent test net to be extended + true + false + + + tag0 + + + + role0 + Role 0 + + + + variable0 + Attribute0 + + + + t0 + 0 + 0 + Test + + dg + + + variable0 + + editable + + + + + + + p0 + 0 + 0 + 1 + + + a0 + regular + p0 + t0 + 1 + + \ No newline at end of file diff --git a/src/test/resources/initial_behavior.xml b/src/test/resources/initial_behavior.xml index e169b58a7b6..795a9e2a1a6 100644 --- a/src/test/resources/initial_behavior.xml +++ b/src/test/resources/initial_behavior.xml @@ -1,31 +1,46 @@ - - + initial_behavior + 1.0.0 Initial behavior - IBH true - - - number - Number - 10000 + false + + IBH + + + boolean + Boolean + True - - - text - Text - Lorem ipsum + + button + Button + Push + + fab + + + + date + Date + 2019-01-01 + + + datetime + Datetime + 2019-01-01T20:00:00.000Z - enumeration Enumeration - Alice - Bob - Carol + + + + + Bob - enumeration_map Enumeration Map @@ -36,19 +51,29 @@ bo - + + file + File + + + fileList + File List + + + i18n + Init I18n + Init I18n field + Default i18n test value + multichoice Multichoice - Alice - Bob - Carol - - Alice - Bob - + + + + + - multichoice_map Multichoice Map @@ -57,290 +82,221 @@ - - al - ca - - - - - boolean - Boolean - True - - - - date - Date - 01.01.2019 - - - file - File + + number + Number + 10000 - - - fileList - File List + + text + Text + Lorem ipsum - user User - - - datetime - Datetime - 01.01.2019 20:00 - - - - button - Button - Push - - fab - - - - - i18n - Init I18n - Init I18n field - Default i18n test value - - - - 1 + t1 379 273 - + Task - editable auto - - DataGroup_0 - grid - - number - - forbidden - - - 0 - 0 - 1 - 2 - 0 - - outline - - - - text - - hidden - - - 2 - 0 - 1 - 2 - 0 - - outline - - - - enumeration - - visible - - - 0 - 1 - 1 - 2 - 0 - - outline - - - - enumeration_map - - editable - - - 2 - 1 - 1 - 2 - 0 - - outline - - - - multichoice - - required - - - 0 - 2 - 1 - 2 - 0 - - outline - - - - multichoice_map - - immediate - - - 2 - 2 - 1 - 2 - 0 - - outline - - - - boolean - - optional - - - 0 - 3 - 1 - 2 - 0 - - outline - - - - date - - editable - required - - - 2 - 3 - 1 - 2 - 0 - - outline - - - - datetime - - immediate - required - - - 0 - 4 - 1 - 2 - 0 - - outline - - - - file - - forbidden - immediate - - - 2 - 4 - 1 - 2 - 0 - - outline - - - - fileList - - hidden - optional - - - 0 - 5 - 1 - 2 - 0 - - outline - - - - user - - hidden - immediate - - - 2 - 5 - 1 - 2 - 0 - - outline - - - - button - - editable - required - immediate - - - 0 - 6 - 1 - 2 - 0 - - outline - - - - i18n - - hidden - optional - immediate - - - 2 - 6 - 1 - 2 - 0 - - outline - - - + + t1_flex + + + number + + forbidden + + + + 0 + 0 + 1 + + + + + text + + hidden + + + + 0 + 0 + 1 + + + + + enumeration + + visible + + + + 0 + 0 + 1 + + + + + enumeration_map + + editable + + + + 0 + 0 + 1 + + + + + multichoice + + editable + true + + + + 0 + 0 + 1 + + + + + multichoice_map + + editable + true + + + + 0 + 0 + 1 + + + + + boolean + + editable + + + + 0 + 0 + 1 + + + + + date + + editable + true + + + + 0 + 0 + 1 + + + + + datetime + + editable + true + true + + + + 0 + 0 + 1 + + + + + file + + forbidden + true + + + + 0 + 0 + 1 + + + + + fileList + + hidden + + + + 0 + 0 + 1 + + + + + user + + hidden + true + + + + 0 + 0 + 1 + + + + + button + + editable + true + true + + + + 0 + 0 + 1 + + + + + i18n + + hidden + true + + + + 0 + 0 + 1 + + + - + \ No newline at end of file diff --git a/src/test/resources/insurance_portal_demo_test.xml b/src/test/resources/insurance_portal_demo_test.xml index 0fa8fcc236b..b8d23400a73 100644 --- a/src/test/resources/insurance_portal_demo_test.xml +++ b/src/test/resources/insurance_portal_demo_test.xml @@ -5505,17 +5505,7 @@ Štát - 109060 - Poistník - - - V zastúpení - 109061 - Poistník - - - Funkcia - 109062 + 109068 Poistník diff --git a/src/test/resources/insurance_portal_demo_test_new.xml b/src/test/resources/insurance_portal_demo_test_new.xml new file mode 100644 index 00000000000..b951488d216 --- /dev/null +++ b/src/test/resources/insurance_portal_demo_test_new.xml @@ -0,0 +1,13167 @@ + + insurance_text + 1.0.0 + Household Insurance + true + false + + HHI + + + + + agent + Agent + + + company + Company + + + psc + PSČ + PSČ + + psc_set + + + + + + + + + mimo_obce + Nachádza sa miesto poistenia mimo obce (extravilán)? + + mimo_obce_set + + + + + + + + + povodne + Bolo miesto poistenia postihnuté povodňou alebo záplavou za posledných 10 rokov? + + povodne_set + + + + + + + + + vodny_tok + Nachádza sa miesto poistenia vo vzdialenosti kratšej ako 300 m od vodného toku? + + vodny_tok_set + + + + + + + + + pocet_rokov_nehnutelnost + Koľko rokov žijete v poisťovanej nehnuteľnosti? + Počet rokov + + + + + + + 6 až 10 + + pocet_rokov_nehnutelnost_set + + + + + + + + + vztah_poistenec_nehnutelnost + Aký je vzťah poisteného k poisťovanej nehnuteľnosti? + Vzťah + + + + + + + vlastník nehnuteľnosti + + vztah_poistenec_nehnutelnost_set + + + + + + + + + pocet_dospelych + Koľko dospelých žije v domácnosti? + Počet + + + + + + + 2 + + pocet_dospelych_set + + + + + + + + + pocet_deti + Koľko detí žije v domácnosti? + Počet + + + + + + + 1 + + pocet_deti_set + + + + + + + + + domace_zviera + Žije v poisťovanej domácnosti pes alebo mačka? + + domace_zviera_set + + + + + + + + + podnikanie + Je nehnuteľnosť využívaná aj na podnikanie? + + podnikanie_set + + + + + + + + + pocet_udalosti + Počet poistných udalostí za posledné 3 roky? + Počet + + + + + + 0 + + pocet_udalosti_set + + + + + + + + + predmet_poistenia + Predmet poistenia + Typ + + + + + + + + predmet_poistenia_set + + + + + + + + + konstrukcia + Konštrukcia múrov + Typ + + + + + + + + tehla a/alebo betón + + konstrukcia_set + + + + + + + + + konstrukcia_strecha + Konštrukcia strechy + Typ + + + + + + + + + škridla + + konstrukcia_strecha_set + + + + + + + + + vek_nehnutelnosti + Koľko rokov má nehnuteľnosť? + Typ + + + + + + + 6 až 10 + + vek_nehnutelnosti_set + + + + + + + + + pocet_izieb + Koľko izieb má nehnuteľnosť? + Počet + + + + + + + + 1 + + pocet_izieb_set + + + + + + + + + pocet_kupelni + Koľko kúpeľní má nehnuteľnosť? + Počet + + + + + + 1 + + pocet_kupelni_set + + + + + + + + + typ_domacnosti + Umiestnenie domácnosti + Typ + + + + + + + + typ_domacnosti_set + + + + + + + + typ_domacnosti_get + + + + + + + + + obyvanost_domacnosti + Obývanosť domácnosti + + + + + trvalá + + obyvanost_domacnosti_set + + + + + + + + + alarm + Je domácnosť zabezpečená funkčným alarmom? + false + + alarm_set + + + + + + + + + zaluzie_rolety + Má domácnosť na oknách vo výške do 3 metrov od okolitého terénu mreže alebo vonkajšie žalúzie alebo rolety? + false + + zaluzie_rolety_set + + + + + + + + + uzemna_platnost + Územná platnosť poistenia + + + + + + uzemna_platnost_set + + + + + + + + + podlahova_plocha_pivnica + Podlahová plocha pivnice + m2 + 0 + + podlahova_plocha_pivnica_set + + + + + + + + + podlahova_plocha_prizemie + Podlahová plocha prízemia + m2 + 0 + + podlahova_plocha_prizemie_set + + + + + + + + + podlahova_plocha_vsetky_poschodia + Podlahová plocha všetkých obytných poschodí + m2 + Okrem prízemia + 0 + + podlahova_plocha_vsetky_poschodia_set + + + + + + + + + podlahova_plocha_garaz + Podlahová plocha garáže + m2 + 0 + + podlahova_plocha_garaz_set + + + + + + + + + spoluucast_nehnutelnost + Poistenie nehnuteľnosti + Spoluúčasť + + + + + + 50.00 € + + spoluucast_nehnutelnost_set + + + + + + + + + odporucana_suma + Odporúčaná poistná suma + Poistná suma + + odporucana_suma_set + + + + + + + + + odporucana_suma_garaz + Garáž + Odporúčaná poistná suma + + odporucana_suma_garaz_set + + + + + + + + + rovnake_miesto_garaz + Rovnaké miesto poistenia garáže? + true + + rovnake_miesto_garaz_set + + + + + + + + + hospodarska_budova + Hospodárska budova + + hospodarska_budova_set + + + + + + + + + hospodarska_budova_poistna_suma + Hospodárska budova + Poistná suma + + hospodarska_budova_poistna_suma_set + + + + + + + + + altanok + Altánok + + altanok_set + + + + + + + + + altanok_suma + Altánok + Poistná suma + + altanok_suma_set + + + + + + + + + pristresok + Prístrešok + + pristresok_set + + + + + + + + + pristresok_suma + Prístrešok + Poistná suma + + pristresok_suma_set + + + + + + + + + chodnik + Chodník, parkovacia plocha + + chodnik_set + + + + + + + + + chodnik_suma + Chodník, parkovacia plocha + Poistná suma + + chodnik_suma_set + + + + + + + + + sauna + Sauna + + sauna_set + + + + + + + + + sauna_suma + Sauna + Poistná suma + + sauna_suma_set + + + + + + + + + elektricka_brana + Elektrická brána + + elektricka_brana_set + + + + + + + + + elektricka_brana_suma + Elektrická brána, oplotenie + Poistná suma + + elektricka_brana_suma_set + + + + + + + + + tenisovy_kurt + Tenisový kurt + + tenisovy_kurt_set + + + + + + + + + tenisovy_kurt_suma + Tenisový kurt + Poistná suma + + tenisovy_kurt_suma_set + + + + + + + + + bazen + Vonkajší bazén + + bazen_set + + + + + + + + + bazen_suma + Vonkajší bazén + Poistná suma + + bazen_suma_set + + + + + + + + + studna + Studňa + + studna_set + + + + + + + + + studna_suma + Studňa + Poistná suma + + studna_suma_set + + + + + + + + + zumpa + Žumpa, septik + + zumpa_set + + + + + + + + + zumpa_suma + Žumpa, septik + Poistná suma + + zumpa_suma_set + + + + + + + + + ine + Iné + + ine_set + + + + + + + + + ine_suma + Iné + Poistná suma + + ine_suma_set + + + + + + + + + stavebne_materialy + Stavebné materiály + + + stavebne_materialy_suma + Stavebné materiály + Poistná suma + + stavebne_materialy_suma_set + + + + + + + + + stavebne_mechanizmy + Stavebné a záhradné mechanizmy + + + stavebne_mechanizmy_suma + Stavebné a záhradné mechanizmy + Poistná suma + + stavebne_mechanizmy_suma_set + + + + + + + + + garaz + Garáž + + garaz_set + + + + + + + + + poistna_suma + Poistná suma + Poistná suma + + poistna_suma_set + + + + + + + + + poistenie_domacnosti_spoluucast + Poistenie domácnosti + Spoluúčasť + + + + + + 50.00 € + + poistenie_domacnosti_spoluucast_set + + + + + + + + + poistna_suma_odporucana + Odporúčaná poistná suma + Poistná suma + + poistna_suma_odporucana_set + + + + + + + + + celkova_podlahova_plocha + Celková podlahová plocha + 0 + + celkova_podlahova_plocha_set + + + 100) + return 25000 + (celkova_podlahova_plocha.rawValue - 100) * 100 as Double + return 250*celkova_podlahova_plocha.rawValue as Double + } + change view_komplet_poistne value { + return Boolean.logicalAnd(view_nehnutelnost_celkova_plocha.rawValue != 0.0, celkova_podlahova_plocha.rawValue != 0.0) + } + ]]> + + + + + + cennosti + Cennosti + + + cennosti_suma + Cennosti + Poistná suma + + cennosti_suma_set + + + + + + + + + umelecke_diela + Umelecké diela + + + umelecke_diela_suma + Umelecké diela + Poistná suma + + umelecke_diela_suma_set + + + + + + + + + elektronika + Elektronické a optické zariadenia + + + elektronika_suma + Elektronické a optické zariadenia + Poistná suma + + elektronika_suma_set + + + + + + + + + presklenie + Špecialne sklá a presklenie + + + presklenie_suma + Špeciálne sklá a presklenie + Poistná suma + + presklenie_suma_set + + + + + + + + + zahradny_nabytok + Záhradné vybavenie a nábytok + + + zahradny_nabytok_suma + Záhradé vybavenie a nábytok + Poistná suma + + zahradny_nabytok_suma_set + + + + + + + + + elektromotory + Elektromotory v domácich spotrebičoch + + + elektromotory_suma + Elektromotory v domácich spotrebičoch + Poistná suma + + elektromotory_suma_set + + + + + + + + + stavebne_sucasti + Stavebné súčasti domácnosti + + + stavebne_sucasti_suma + Stavebné súčasti domácností + Poistná suma + + stavebne_sucasti_suma_set + + + + + + + + + sportove_naradie + Športové náradie + + + sportove_naradie_suma + Športové náradie + Poistná suma + + sportove_naradie_suma_set + + + + + + + + + ine_domacnost + Iné + + + ine_domacnost_suma + Iné + Poistná suma + + ine_domacnost_suma_set + + + + + + + + + poistna_suma_trvalo + Poistná suma + Poistná suma + + poistna_suma_trvalo_set + + + + + + + + + poistna_suma_docasne + Poistná suma + Poistná suma + + poistna_suma_docasne_set + + + + + + + + + celkova_poistna_suma + Celková poistná suma + + + celkove_poistne + Celkové poistné + + + poistenie_zodpovednosti + Poistenie zodpovednosti z vlastníctva nehnuteľnosti do výšky + Poistná suma + + + + + + + + + poistenie_zodpovednosti_set + + + + + + + + + zodpovednost_za_skodu + Zodpovednosť za škodu členov domácnosti + Eur + + + + + + + + + zodpovednost_za_skodu_set + + + + + + + + + periodicita_platby + PERIODICITA PLATBY POISTNÉHO + + + + + + ročná + + periodicita_platby_set + + + + + + + + + zlava_za_ine_poistenie + ZĽAVA ZA INÉ POISTENIE V PREMIUM + + zlava_za_ine_poistenie_set + + + + + + + + + obchodna_zlava + OBCHODNÁ ZĽAVA + + + + + + + + + + obchodna_zlava_set + + + + + + + + + akciova_zlava + AKCIOVÁ ZĽAVA + + akciova_zlava_set + + + + + + + + + alarm_zlava + ZABEZPEČENIE DOMÁCNOSTI ALARMOM + + + zaciatok_poistenia + Začiatok poistenia + + + doba_urcita + Poistenie na dobu určitú + + doba_urcita_set + + + + + + + + + koniec_poistenia + Koniec poistenia + + + vinkulacia_v_prospech + V prospech + Údaje o vinkulácii + + + vinkulacia_cislo_zmluvy + Číslo úverovej zmluvy + Údaje o vinkulácii + + + sposob_platenia + Spôsob platenia + + + + + + sposob_platenia_set + + + + + + + + + poistnik_typ + Typ subjektu + Poistník + + + + + + fyzická osoba + + poistnik_typ_set + + + + + + + + + poistnik_titul_pred + Titul pred menom + Poistník + + poistnik_titul_pred_set + + + + + + + + + poistnik_titul_za + Titul za menom + Poistník + + poistnik_titul_za_set + + + + + + + + + poistnik_meno + Meno + Poistník + + poistnik_meno_set + + + + + + + + + poistnik_priezvisko + Priezvisko + Poistník + + poistnik_priezvisko_set + + + + + + + + + poistnik_obchodne_meno + Obchodné meno + Poistník + + poistnik_obchodne_meno_set + + + + + + + + + poistnik_statna_prislusnost + Štátna príslušnosť + Poistník + + + + + + + + + + poistnik_statna_prislusnost_set + + + + + + + + + poistnik_datum_narodenia + Dátum narodenia + Poistník + + poistnik_datum_narodenia_set + + + + + + + + + poistnik_rodne_cislo + Rodné číslo + Poistník + + poistnik_rodne_cislo_set + + + + + + + + + poistnik_preukaz + Typ preukazu + Poistník + + + + + + + poistnik_preukaz_set + + + + + + + + + poistnik_preukaz_cislo + Číslo preukazu + Poistník + + poistnik_preukaz_cislo_set + + + + + + + + + poistnik_telefon + Telefónne číslo + Poistník + + poistnik_telefon_set + + + + + + + + + poistnik_email + Email + Poistník + + poistnik_email_set + + + + + + + + + poisteny_ina_osoba + Poistený je iná osoba + Poistený a poistenec sú rôzne osoby + false + + poisteny_ina_osoba_set + + + + + + + + + poisteny_typ + Typ subjektu + Poistený + + + + + + fyzická osoba + + poisteny_typ_set + + + + + + + + + poisteny_titul_pred + Titul pred menom + Poistený + + + poisteny_titul_za + Titul za menom + Poistený + + + poisteny_meno + Meno + Poistený + + + poisteny_priezvisko + Priezvisko + Poistený + + + poisteny_obchodne_meno + Obchodné meno + Poistený + + + poisteny_statna_prislusnost + Štátna príslušnosť + Poistený + + + + + + + + SK + + + poisteny_datum_narodenia + Dátum narodenia + Poistený + + + poisteny_rodne_cislo + Rodné číslo + Poistený + + + poisteny_preukaz + Typ preukazu + Poistený + + + + + + + poisteny_preukaz_set + + + + + + + + + poisteny_preukaz_cislo + Číslo preukazu + Poistený + + + poisteny_telefon + Telefónne číslo + Poistený + + + poisteny_email + Email + Poistený + + + korespondencna_rovnaka + Rovnaká ako trvalý pobyt + Korešpondenčná adresa + true + + korespondencna_rovnaka_set + + + + + + + + + trvaly_pobyt_rovnaky + Rovnaká ako miesto poistenia + Adresa trvalého pobytu + true + + trvaly_pobyt_rovnaky_set + + + + + + + + + trvaly_pobyt_ulica + Ulica + Trvalý pobyt/Sídlo + + trvaly_pobyt_ulica_set + + + + + + + + + trvaly_pobyt_cislo + Súpisné a orientačné číslo + Trvalý pobyt/Sídlo + + trvaly_pobyt_cislo_set + + + + + + + + + trvaly_pobyt_psc + PSČ + Trvalý pobyt/Sídlo + + trvaly_pobyt_psc_set + + + + + + + + + trvaly_pobyt_obec + Obec + Trvalý pobyt/Sídlo + + trvaly_pobyt_obec_set + + + + + + + + + korespondencna_ulica + Ulica + Korešpondenčná adresa + + + korespondencna_cislo + Súpisné a orientačné číslo + Korešpondenčná adresa + + + korespondencna_psc + PSČ + Korešpondenčná adresa + + + korespondencna_obec + Obec + Korešpondenčná adresa + + + miesto_poistenia_ulica + Ulica + Miesto poistenia + + miesto_poistenia_ulica_set + + + + + + + + + miesto_poistenia_cislo + Súpisné a orientačné číslo + Miesto poistenia + + miesto_poistenia_cislo_set + + + + + + + + + miesto_poistenia_psc + PSČ + Miesto poistenia + + miesto_poistenia_psc_set + + + + + + + + + miesto_poistenia_obec + Obec + Miesto poistenia + + miesto_poistenia_obec_set + + + + + + + + + garaz_ulica + Ulica + Garáž + + + garaz_cislo + Súpisné a orientačné číslo + Garáž + + + garaz_psc + PSČ + Garáž + + + garaz_obec + Obec + Garáž + + + poistnik_ico + IČO + Poistník + + poistnik_ico_set + + + + + + + + + poisteny_ico + IČO + Poistený + + + indexacia + Zriaďuje sa indexácia poistnej sumy? + + + poistnik_v_zastupeni + V zastúpení + Poistník + + poistnik_v_zastupeni_set + + + + + + + + + poistnik_konatel + Funkcia konateľa + Poistník + + poistnik_konatel_set + + + + + + + + + poisteny_v_zastupeni + V zastúpení + Poistený + + + poisteny_konatel + Funkcia konateľa + Poistený + + + povod_financii + Pôvod finančných prostriedkov + + + osobitne_vyjadrenia + Osobitné vyjadrenia týkajúce sa poisteného alebo poistníka + + area + + + + poistnik_suhlas_gdpr + Poistník udeľuje poisťovateľovi súhlas so spracovaním osobných údajov na marketingové účely + + + poistnik_stat + Štát + Poistník + + + datum_valuty + Dátum valuty + + + predcislo_uctu + Predčíslo účtu + + + cislo_uctu + Číslo účtu + + + predcislo_protiuctu + Predčíslo protiúčtu + + + cislo_protiuctu + Číslo protiúčtu + + + kod_banky_protiuctu + Kód banky protiúčtu + + + nazov_protiuctu + Názov protiúčtu + + + suma + Suma + + + mena + Mena + + + kurz + Kurz + + + zostatok + Zostatok + + + popis_obratu + Popis obratu + + + e2e_reference + E2E reference + + + variabilny_symbol + Variabilný symbol + + + konstantny_symbol + Konštantný symbol + + + specificky_symbol + Špecifický symbol + + + poznamka + Poznámka + + + cislo_vypisu + Číslo výpisu + + + id_protiuctu_1 + Identifikácia protiúčtu 1 + + + id_protiuctu_2 + Identifikácia protiúčtu 2 + + + id_protiuctu_3 + Identifikácia protiúčtu 3 + + + id_protiuctu_4 + Identifikácia protiúčtu 4 + + + sprava_prijimatelovi_1 + Správa pre prijímateľa 1 + + + sprava_prijimatelovi_2 + Správa pre prijímateľa 2 + + + sprava_prijimatelovi_3 + Správa pre prijímateľa 3 + + + sprava_prijimatelovi_4 + Správa pre prijímateľa 4 + + + koeficient_lokalita_nehnutelnosti + Koeficient - Lokalita nehnutelnosť + 1 + + koeficient_lokalita_nehnutelnosti_set + + + + + + + + + koeficient_extravilan + Koeficient - Nachádza sa mimo obce (extravilán)? + 1 + + koeficient_extravilan_set + + + + + + + + + koeficient_povodne + Koeficient - Bolo miesto poistenia postihnuté povodňou za posledných 10 rokov? + 1 + + koeficient_povodne_set + + + + + + + + + koeficient_vodny_tok + Koeficient - Nachádza sa nehnuteľnosť vo vzdialenosti kratšej ako 300m od vodného toku? + 1 + + koeficient_vodny_tok_set + + + + + + + + + koeficient_pocet_rokov_nehnutelnost + Koeficient - Koľko rokov žijete v poisťovanej nehnuteľnosti? + 1 + + koeficient_pocet_rokov_nehnutelnost_set + + + + + + + + + koeficient_vztah_poistenec_nehnutelnost + Koeficient - Aký je vzťah poisteného k poisťovanej nehnuteľnosti? + 1 + + koeficient_vztah_poistenec_nehnutelnost_set + + + + + + + + + koeficient_pocet_dospelych + Koeficient - Koľko dospelých žije v domácnosti? + 1 + + koeficient_pocet_dospelych_set + + + + + + + + + koeficient_pocet_deti + Koeficient - Koľko detí žije v domácnosti? + 1 + + koeficient_pocet_deti_set + + + + + + + + + koeficient_domace_zviera + Koeficient - Žije v poisťovanej domácnosti pes alebo mačka? + 1 + + koeficient_domace_zviera_set + + + + + + + + + koeficient_podnikanie + Koeficient - Je nehnuteľnosť využívaná aj na podnikanie? + 1 + + koeficient_podnikanie_set + + + + + + + + + koeficient_pocet_udalosti + Koeficient - Počet poistných udalostí za posledné 3 roky? + 1 + + koeficient_pocet_udalosti_set + + + + + + + + + koeficient_zakladne_informacie + ZÁKLADNÉ INFORMÁCIE koeficient + 1 + + koeficient_zakladne_informacie_set + + + + + + + + + koeficient_lokalita_domacnost + Koeficient - Lokalita sadzba domácnosť + 1 + + + koeficient_lokalita_nehnutelnost + Koeficient - Lokalita sadzba nehnutelnosť + 1 + + + koeficient_predmet_poistenia + Koeficient - Predmet poistenia + 1 + + koeficient_predmet_poistenia_set + + + + + + + + + koeficient_konstrukcia + Koeficient - Konštrukcia múrov + 1 + + koeficient_konstrukcia_set + + + + + + + + + koeficient_konstrukcia_strecha + Koeficient - Konštrukcia strechy + 1 + + koeficient_konstrukcia_strecha_set + + + + + + + + + koeficient_vek_nehnutelnosti + Koeficient - Koľko rokov má nehnuteľnosť? + 1.02 + + koeficient_vek_nehnutelnosti_set + + + + + + + + + koeficient_pocet_izieb + Koeficient - Koľko izieb má nehnuteľnosť? + + koeficient_pocet_izieb_set + + + + + + + + + koeficient_pocet_kupelni + Koeficient - Koľko kúpeľní má nehnuteľnosť? + + koeficient_pocet_kupelni_set + + + + + + + + + koeficient_nehnutelnost + NEHNUTEĽNOSŤ koeficient + + koeficient_nehnutelnost_set + + + + + + + + + koeficient_typ_domacnosti + Koeficient - Umiestnenie domácnosti + 1.0 + + koeficient_typ_domacnosti_set + + + + + + + + + koeficient_obyvanost_domacnosti + Koeficient - Obývanosť domácnosti + 1.0 + + koeficient_obyvanost_domacnosti_set + + + + + + + + + koeficient_alarm + Koeficient - Je domácnosť zabezpečená funkčným alarmom? + 1.0 + + + koeficient_zaluzie_rolety + Koeficient - Má domácnosť na oknách vo výške do 3 metrov od okolitého terénu mreže / vonkajšie žalúzie + alebo rolety? + 1.0 + + koeficient_zaluzie_rolety_set + + + + + + + + + koeficient_domacnost + DOMÁCNOSŤ koeficient + 0.95 + + koeficient_domacnost_set + + + + + + + + + koeficient_poistenie_zodpovednosti + Koeficient - Poistenie zodpovednosti z vlastníctva nehnuteľnosti + + + koeficient_zodpovednost_za_skodu + Koeficient - Zodpovednosť za škodu členov domácnosti + 0 + + + koeficient_uzemna_platnost + Koeficient - Územná platnosť poistenia + 1 + + + koeficient_zodpovednost_celkovo + Koeficient - Zodpovednosť celkovo + 0 + + + koeficient_lokalita_byt + Koeficient - Lokalita - byt + 0 + + koeficient_lokalita_byt_set + + + + + + + + + koeficient_lokalita_pivnica + Koeficient - Lokalita - pivnica + 0 + + + koeficient_lokalita_prizemie + Koeficient - Lokalita - prízemie + 0 + + + koeficient_lokalita_poschodia + Koeficient - Lokalita - obytné poschodie + 0 + + + koeficient_lokalita_garaz + Koeficient - Lokalita - garáž + + + koeficient_garaz + Koeficient - Garáž + + + koeficient_hospodarska_budova + Koeficient - Hospodárska budova + + + koeficient_altanok + Koeficient - Altánok + + + koeficient_pristresok + Koeficient - Prístrešok + + + koeficient_chodnik + Koeficient - Chodník, parkovacia plocha + + + koeficient_sauna + Koeficient - Sauna + + + koeficient_elektricka_brana + Koeficient - Elektrická brána, oplotenie + + + koeficient_tenisovy_kurt + Koeficient - Tenisový kurt + + + koeficient_bazen + Koeficient - Vonkajší bazén + + + koeficient_studna + Koeficient - Studňa + + + koeficient_zumpa + Koeficient - Žumpa, septik + + + koeficient_ine + Koeficient - Iné + + + koeficient_stavebne_materialy + Koeficient - Stavebné materiály + + + koeficient_stavebne_mechanizmy + Koeficient - Stavebné a záhradné mechanizmy + + + koeficient_cennosti + Koeficient - Cennosti + + + koeficient_umelecke_diela + Koeficient - Umelecké diela + + + koeficient_elektronika + Koeficient - Elektronické a optické zariadneia + + + koeficient_presklenie + Koeficient - Špecialne sklá a presklenie + + + koeficient_zahradny_nabytok + Koeficient - Záhradné vybavenie a nábytok + + + koeficient_elektromotory + Koeficient - Elektromotory v domácich spotrebičoch + + + koeficient_stavebne_sucasti + Koeficient - Stavebné súčasti domácností + + + koeficient_sportove_naradie + Koeficient - Športové náradie + + + koeficient_ine_domacnost + Koeficient - Iné + + + koeficient_domacnost_lokalita + Koeficient - Domácnosť - lokalita + + + koeficient_poistenie_zodpovednosti_clenov + Koeficient - Zodpovednosť za škodu členov domácnosti + + + koeficient_nehnutelnost_spoluucast + Koeficient - Poistenie nehnuteľnosti - spoluúčasť + 1 + + + koeficient_domacnost_spoluucast + Koeficient - Poistenie domácnosti - spoluúčasť + 1 + + koeficient_domacnost_spoluucast_set + + + + + + + + + koeficient_garaz_umiestnenie + Koeficient - Garáž umiestnenie + 1 + + + koeficient_periodicita_platby + Koeficient - PERIODICITA PLATBY POISTNÉHO + 0.95 + + + koeficient_zlava_za_ine_poistenie + Koeficient - ZĽAVA ZA INÉ POISTENIE V PREMIUM + 1 + + + koeficient_obchodna_zlava + Koeficient - OBCHODNÁ ZĽAVA + 1 + + + koeficient_akciova_zlava + Koeficient - AKCIOVÁ ZĽAVA + 1 + + + koeficient_kompletne_poistenie + Koeficient - KOMPLETNÉ POISTENIE + 1 + + + view_lokalita + Lokalita + Typ + + view_lokalita_set + + + + + + + + + view_nehnutelnost_obec + Obec + + + + + view_nehnutelnost_obec_set + + + + + + + + + view_nehnutelnost_celkova_plocha + Celková podlahová plocha + m2 + 0 + + view_nehnutelnost_celkova_plocha_set + + + 0 } + make celkova_podlahova_plocha,editable on t363 when { view_nehnutelnost_celkova_plocha.rawValue == null } + make celkova_podlahova_plocha,editable on t363 when { view_nehnutelnost_celkova_plocha.rawValue == 0 as Double } + change celkova_podlahova_plocha value { + if (dummy_data.rawValue == "Nehnutelnost a domacnost" ) + return view_nehnutelnost_celkova_plocha.rawValue as Double + return celkova_podlahova_plocha.rawValue as Double + } + change view_komplet_poistne value { + return Boolean.logicalAnd(view_nehnutelnost_celkova_plocha.rawValue != 0.0, celkova_podlahova_plocha.rawValue != 0.0) + } + ]]> + + + + + + view_nehnutelnost_poistne + Poistenie nehnuteľnosti + Poistné + 0 + + view_nehnutelnost_poistne_set + + + + + + + + + view_garaz_poistne + Garáž + Poistné + + view_garaz_poistne_set + + + + + + + + + view_hospodarska_budova_poistne + Hospodárska budova + Poistné + + view_hospodarska_budova_poistne_set + + + + + + + + + view_altanok_poistne + Altánok + Poistné + + view_altanok_poistne_set + + + + + + + + + view_pristresok_poistne + Prístrešok + Poistné + + view_pristresok_poistne_set + + + + + + + + + view_chodnik_poistne + Chodník, parkovacia plocha + Poistné + + view_chodnik_poistne_set + + + + + + + + + view_sauna_poistne + Sauna + Poistné + + view_sauna_poistne_set + + + + + + + + + view_brana_poistne + Elektrická brána, oplotenie + Poistné + + view_brana_poistne_set + + + + + + + + + view_tenisovy_kurt_poistne + Tenisový kurt + Poistné + + view_tenisovy_kurt_poistne_set + + + + + + + + + view_bazen_poistne + Vonkajší bazén + Poistné + + view_bazen_poistne_set + + + + + + + + + view_studna_poistne + Studňa + Poistné + + view_studna_poistne_set + + + + + + + + + view_zumpa_poistne + Žumpa, septik + Poistné + + view_zumpa_poistne_set + + + + + + + + + view_ine_stavby_poistne + Iné + Poistné + + view_ine_stavby_poistne_set + + + + + + + + + view_stavebne_materialy_poistne + Stavebné materiály + Poistné + + view_stavebne_materialy_poistne_set + + + + + + + + + view_mechanizmy_poistne + Stavebné a záhradné mechanizmy + Poistné + + view_mechanizmy_poistne_set + + + + + + + + + view_celkova_suma + Celková poistná suma + + + view_celkove_poistne + Celkové poistné + + + view_garaz_poistna_suma + Garáž + Poistná suma + + view_garaz_poistna_suma_set + + + + + + + + + view_domacnost_poistne + Poistenie domácnosti + Poistné + + view_domacnost_poistne_set + + + + + + + + + view_cennosti_poistne + Cennosti + Poistné + + view_cennosti_poistne_set + + + + + + + + + view_umelecke_deial_poistne + Umelecké diela + Poistné + + view_umelecke_deial_poistne_set + + + + + + + + + view_optika_poistne + Elektronické a optické zariadenia + Poistné + + view_optika_poistne_set + + + + + + + + + view_presklenie_poistne + Špeciálne sklá a presklenie + Poistné + + view_presklenie_poistne_set + + + + + + + + + view_zahradny_nabytok_poistne + Záhradé vybavenie a nábytok + Poistné + + view_zahradny_nabytok_poistne_set + + + + + + + + + view_elektromotory_poistne + Elektromotory v domácich spotrebičoch + Poistné + + view_elektromotory_poistne_set + + + + + + + + + view_stavebne_sucasti_poistne + Stavebné súčasti domácností + Poistné + + view_stavebne_sucasti_poistne_set + + + + + + + + + view_sportove_naradie_poistne + športové náradie + Poistné + + view_sportove_naradie_poistne_set + + + + + + + + + view_ine_poistne + Iné + Poistné + + view_ine_poistne_set + + + + + + + + + view_nehnutelnost_celkove_poistne + Celkové poistenie nehnuteľnosti + Poistné + + view_nehnutelnost_celkove_poistne_set + + + + + + + + + view_domacnost_celkove_poistne + Celkové poistenie domácnosti + Poistné + + view_domacnost_celkove_poistne_set + + + + + + + + + view_zodpovednost_celkove_poistne + Celkové poistenie zodpovednosti za škodu + Poistné + + view_zodpovednost_celkove_poistne_set + + + + + + + + + view_rocne_celkove_poistne + ROČNÉ POISTNÉ CELKOM + + view_rocne_celkove_poistne_set + + + + + + + + + view_komplet_poistne + KOMPLETNÉ POISTENIE + + view_komplet_poistne_set + + + + + + + + + bezne_poistenie + BEŽNÉ POISTNÉ + + bezne_poistenie_set + + + + + + + + + view_variabilny_symbol + Variabilný symbol + + + view_nehnutelnost_zodpovednost_poistne + Poistenie zodpovednosti z vlastníctva nehnuteľnosti + Poistné + + view_nehnutelnost_zodpovednost_poistne_set + + + + + + + + + poistenie_zodpovednosti_clenov + Zodpovednosť za škodu členov domácnosti + Poistné + + poistenie_zodpovednosti_clenov_set + + + + + + + + + vyska_splatky + Výška splátky poistného + + + cislo_zmluvy + Číslo zmluvy + 0000000000 + + cislo_zmluvy_set + + + + + + + + + datum_navrhu + Dátum dojednania návrhu na uzavretie poistnej zmluvy + + + pdf_ponuka + Ponuka PDF + Automaticky generované + + + pdf_zmluva + Zmluva PDF + Automaticky generované + + + dummy_data + Dummy + + + t154 + 620 + 60 + Základné informácie + + agent + + true + + + + t154_flex + + + psc + + editable + true + + + + 0 + 0 + 1 + + + + + view_nehnutelnost_obec + + editable + true + + + + 0 + 0 + 1 + + + + + mimo_obce + + editable + true + + + + 0 + 0 + 1 + + + + + povodne + + editable + true + + + + 0 + 0 + 1 + + + + + vodny_tok + + editable + true + + + + 0 + 0 + 1 + + + + + pocet_rokov_nehnutelnost + + editable + true + + + + 0 + 0 + 1 + + + + + vztah_poistenec_nehnutelnost + + editable + true + + + + 0 + 0 + 1 + + + + + pocet_dospelych + + editable + true + + + + 0 + 0 + 1 + + + + + pocet_deti + + editable + true + + + + 0 + 0 + 1 + + + + + domace_zviera + + editable + true + + + + 0 + 0 + 1 + + + + + podnikanie + + editable + true + + + + 0 + 0 + 1 + + + + + pocet_udalosti + + editable + true + + + + 0 + 0 + 1 + + + + + 1 + + + + t155 + 620 + 220 + Nehnuteľnosť + + agent + + true + + + + t155_flex + + + predmet_poistenia + + editable + true + + + predmet_poistenia_get + + + + + + + + + 0 + 0 + 1 + + + + + spoluucast_nehnutelnost + + editable + + + + 0 + 0 + 1 + + + + + pocet_izieb + + editable + true + + + + 0 + 0 + 1 + + + + + pocet_kupelni + + editable + true + + + + 0 + 0 + 1 + + + + + poistenie_zodpovednosti + + editable + true + + + + 0 + 0 + 1 + + + + + podlahova_plocha_pivnica + + editable + true + + + + 0 + 0 + 1 + + + + + podlahova_plocha_prizemie + + editable + true + + + + 0 + 0 + 1 + + + + + podlahova_plocha_vsetky_poschodia + + editable + true + + + + 0 + 0 + 1 + + + + + view_nehnutelnost_celkova_plocha + + visible + + + + 0 + 0 + 1 + + + + + konstrukcia + + editable + + + + 0 + 0 + 1 + + + + + konstrukcia_strecha + + hidden + + + + 0 + 0 + 1 + + + + + vek_nehnutelnosti + + editable + + + + 0 + 0 + 1 + + + + + 2 + + + + t1618 + 1180 + 260 + Údaje o zmluve - N + + agent + + true + + + + t1618_flex + + + cislo_zmluvy + + visible + + + + 0 + 0 + 1 + + + + + zaciatok_poistenia + + editable + true + + + + 0 + 0 + 1 + + + + + doba_urcita + + hidden + + + + 0 + 0 + 1 + + + + + koniec_poistenia + + hidden + + + + 0 + 0 + 1 + + + + + vinkulacia_v_prospech + + editable + + + + 0 + 0 + 1 + + + + + vinkulacia_cislo_zmluvy + + editable + + + + 0 + 0 + 1 + + + + + indexacia + + editable + + + + 0 + 0 + 1 + + + + + sposob_platenia + + editable + true + + + + 0 + 0 + 1 + + + + + povod_financii + + hidden + + + + 0 + 0 + 1 + + + + + osobitne_vyjadrenia + + editable + + + + 0 + 0 + 1 + + + + + poistnik_suhlas_gdpr + + editable + + + + 0 + 0 + 1 + + + + + pdf_zmluva + + visible + + + + 0 + 0 + 1 + + + + + 9 + + + + t1661 + 1185 + 898 + Údaje o zmluve - D + + agent + + true + + + + t1661_flex + + + cislo_zmluvy + + visible + + + + 0 + 0 + 1 + + + + + zaciatok_poistenia + + editable + true + + + + 0 + 0 + 1 + + + + + doba_urcita + + hidden + + + + 0 + 0 + 1 + + + + + koniec_poistenia + + hidden + + + + 0 + 0 + 1 + + + + + vinkulacia_v_prospech + + editable + + + + 0 + 0 + 1 + + + + + vinkulacia_cislo_zmluvy + + editable + + + + 0 + 0 + 1 + + + + + indexacia + + editable + + + + 0 + 0 + 1 + + + + + sposob_platenia + + editable + true + + + + 0 + 0 + 1 + + + + + povod_financii + + hidden + + + + 0 + 0 + 1 + + + + + osobitne_vyjadrenia + + editable + + + + 0 + 0 + 1 + + + + + poistnik_suhlas_gdpr + + editable + + + + 0 + 0 + 1 + + + + + pdf_zmluva + + visible + + + + 0 + 0 + 1 + + + + + 9 + + + + t2 + 260 + 300 + Iba nehnuteľnosť + home + + agent + + true + + + + t2_flex + + + dummy_data + + forbidden + + + dummy_data_get + + + + + + + + + 0 + 0 + 1 + + + + + 1 + + + + t2014 + 2237 + 743 + Údaje o zmluve (view) + + agent + + true + + + + t2014_flex + + + cislo_zmluvy + + visible + + + + 0 + 0 + 1 + + + + + zaciatok_poistenia + + visible + + + + 0 + 0 + 1 + + + + + doba_urcita + + visible + + + + 0 + 0 + 1 + + + + + koniec_poistenia + + visible + + + + 0 + 0 + 1 + + + + + vinkulacia_v_prospech + + visible + + + + 0 + 0 + 1 + + + + + vinkulacia_cislo_zmluvy + + visible + + + + 0 + 0 + 1 + + + + + sposob_platenia + + visible + + + + 0 + 0 + 1 + + + + + pdf_zmluva + + visible + + + + 0 + 0 + 1 + + + + + 8 + + + + t2015 + 2229 + 38 + Základné informácie (view) + + agent + + true + + + + t2015_flex + + + view_nehnutelnost_obec + + visible + + + + 0 + 0 + 1 + + + + + psc + + visible + + + + 0 + 0 + 1 + + + + + view_lokalita + + visible + + + + 0 + 0 + 1 + + + + + mimo_obce + + visible + + + + 0 + 0 + 1 + + + + + povodne + + visible + + + + 0 + 0 + 1 + + + + + vodny_tok + + visible + + + + 0 + 0 + 1 + + + + + pocet_rokov_nehnutelnost + + visible + + + + 0 + 0 + 1 + + + + + vztah_poistenec_nehnutelnost + + visible + + + + 0 + 0 + 1 + + + + + pocet_dospelych + + visible + + + + 0 + 0 + 1 + + + + + pocet_deti + + visible + + + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + + domace_zviera + + visible + + + + 0 + 0 + 1 + + + + + podnikanie + + visible + + + + 0 + 0 + 1 + + + + + pocet_udalosti + + visible + + + + 0 + 0 + 1 + + + + + 1 + + + + t2016 + 2235 + 646 + Údaje o poistníkovi a mieste poistenia (view) + + agent + + true + + + + t2016_flex + + + poistnik_typ + + visible + + + + 0 + 0 + 1 + + + + + poistnik_titul_pred + + visible + + + + 0 + 0 + 1 + + + + + poistnik_titul_za + + visible + + + + 0 + 0 + 1 + + + + + poistnik_meno + + visible + + + + 0 + 0 + 1 + + + + + poistnik_priezvisko + + visible + + + + 0 + 0 + 1 + + + + + poistnik_obchodne_meno + + visible + + + + 0 + 0 + 1 + + + + + poistnik_statna_prislusnost + + visible + + + + 0 + 0 + 1 + + + + + poistnik_datum_narodenia + + visible + + + + 0 + 0 + 1 + + + + + poistnik_rodne_cislo + + visible + + + + 0 + 0 + 1 + + + + + poistnik_preukaz + + visible + + + + 0 + 0 + 1 + + + + + poistnik_preukaz_cislo + + visible + + + + 0 + 0 + 1 + + + + + poistnik_telefon + + visible + + + + 0 + 0 + 1 + + + + + poistnik_email + + visible + + + + 0 + 0 + 1 + + + + + poisteny_ina_osoba + + visible + + + + 0 + 0 + 1 + + + + + poisteny_typ + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_titul_pred + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_titul_za + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_meno + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_priezvisko + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_obchodne_meno + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_statna_prislusnost + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_datum_narodenia + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_rodne_cislo + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_preukaz + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_preukaz_cislo + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_telefon + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_email + + hidden + + + + 0 + 0 + 1 + + + + + trvaly_pobyt_ulica + + visible + + + + 0 + 0 + 1 + + + + + trvaly_pobyt_cislo + + visible + + + + 0 + 0 + 1 + + + + + trvaly_pobyt_psc + + visible + + + + 0 + 0 + 1 + + + + + trvaly_pobyt_obec + + visible + + + + 0 + 0 + 1 + + + + + korespondencna_ulica + + visible + + + + 0 + 0 + 1 + + + + + korespondencna_cislo + + visible + + + + 0 + 0 + 1 + + + + + korespondencna_psc + + visible + + + + 0 + 0 + 1 + + + + + korespondencna_obec + + visible + + + + 0 + 0 + 1 + + + + + miesto_poistenia_ulica + + visible + + + + 0 + 0 + 1 + + + + + miesto_poistenia_cislo + + visible + + + + 0 + 0 + 1 + + + + + miesto_poistenia_psc + + visible + + + + 0 + 0 + 1 + + + + + miesto_poistenia_obec + + visible + + + + 0 + 0 + 1 + + + + + garaz_ulica + + visible + + + + 0 + 0 + 1 + + + + + garaz_cislo + + visible + + + + 0 + 0 + 1 + + + + + garaz_psc + + visible + + + + 0 + 0 + 1 + + + + + garaz_obec + + visible + + + + 0 + 0 + 1 + + + + + 7 + + + + t2017 + 2233 + 549 + Doplnkové poistenie domácnosti (view) + + agent + + true + + + + t2017_flex + + + cennosti + + visible + + + + 0 + 0 + 1 + + + + + cennosti_suma + + visible + + + + 0 + 0 + 1 + + + + + view_cennosti_poistne + + visible + + + + 0 + 0 + 1 + + + + + umelecke_diela + + visible + + + + 0 + 0 + 1 + + + + + umelecke_diela_suma + + visible + + + + 0 + 0 + 1 + + + + + view_umelecke_deial_poistne + + visible + + + + 0 + 0 + 1 + + + + + elektronika + + visible + + + + 0 + 0 + 1 + + + + + elektronika_suma + + visible + + + + 0 + 0 + 1 + + + + + view_optika_poistne + + visible + + + + 0 + 0 + 1 + + + + + presklenie + + visible + + + + 0 + 0 + 1 + + + + + presklenie_suma + + visible + + + + 0 + 0 + 1 + + + + + view_presklenie_poistne + + visible + + + + 0 + 0 + 1 + + + + + zahradny_nabytok + + visible + + + + 0 + 0 + 1 + + + + + zahradny_nabytok_suma + + visible + + + + 0 + 0 + 1 + + + + + view_zahradny_nabytok_poistne + + visible + + + + 0 + 0 + 1 + + + + + elektromotory + + visible + + + + 0 + 0 + 1 + + + + + elektromotory_suma + + visible + + + + 0 + 0 + 1 + + + + + view_elektromotory_poistne + + visible + + + + 0 + 0 + 1 + + + + + stavebne_sucasti + + visible + + + + 0 + 0 + 1 + + + + + stavebne_sucasti_suma + + visible + + + + 0 + 0 + 1 + + + + + view_stavebne_sucasti_poistne + + visible + + + + 0 + 0 + 1 + + + + + sportove_naradie + + visible + + + + 0 + 0 + 1 + + + + + sportove_naradie_suma + + visible + + + + 0 + 0 + 1 + + + + + view_sportove_naradie_poistne + + visible + + + + 0 + 0 + 1 + + + + + ine_domacnost + + visible + + + + 0 + 0 + 1 + + + + + ine_domacnost_suma + + visible + + + + 0 + 0 + 1 + + + + + view_ine_poistne + + visible + + + + 0 + 0 + 1 + + + + + 6 + + + + t2018 + 2231 + 451 + Domácnosť (view) + + agent + + true + + + + t2018_flex + + + typ_domacnosti + + visible + + + + 0 + 0 + 1 + + + + + celkova_podlahova_plocha + + visible + + + + 0 + 0 + 1 + + + + + obyvanost_domacnosti + + visible + + + + 0 + 0 + 1 + + + + + alarm + + visible + + + + 0 + 0 + 1 + + + + + zaluzie_rolety + + visible + + + + 0 + 0 + 1 + + + + + 5 + + + + t2019 + 2231 + 143 + Nehnuteľnosť (view) + + agent + + true + + + + t2019_flex + + + predmet_poistenia + + visible + + + + 0 + 0 + 1 + + + + + podlahova_plocha_pivnica + + visible + + + + 0 + 0 + 1 + + + + + podlahova_plocha_prizemie + + visible + + + + 0 + 0 + 1 + + + + + podlahova_plocha_vsetky_poschodia + + visible + + + + 0 + 0 + 1 + + + + + podlahova_plocha_garaz + + visible + + + + 0 + 0 + 1 + + + + + view_nehnutelnost_celkova_plocha + + visible + + + + 0 + 0 + 1 + + + + + konstrukcia + + visible + + + + 0 + 0 + 1 + + + + + konstrukcia_strecha + + visible + + + + 0 + 0 + 1 + + + + + vek_nehnutelnosti + + visible + + + + 0 + 0 + 1 + + + + + pocet_izieb + + visible + + + + 0 + 0 + 1 + + + + + pocet_kupelni + + visible + + + + 0 + 0 + 1 + + + + + poistenie_zodpovednosti + + visible + + + + 0 + 0 + 1 + + + + + 2 + + + + t2020 + 2233 + 247 + Doplnkové poistenie nehnuteľnosti (view) + + agent + + true + + + + t2020_flex + + + stavebne_materialy + + visible + + + + 0 + 0 + 1 + + + + + stavebne_materialy_suma + + visible + + + + 0 + 0 + 1 + + + + + view_stavebne_materialy_poistne + + visible + + + + 0 + 0 + 1 + + + + + stavebne_mechanizmy + + visible + + + + 0 + 0 + 1 + + + + + stavebne_mechanizmy_suma + + visible + + + + 0 + 0 + 1 + + + + + view_mechanizmy_poistne + + visible + + + + 0 + 0 + 1 + + + + + 3 + + + + t2021 + 2233 + 351 + Vedľajšie stavby (view) + + agent + + true + + + + t2021_flex + + + garaz + + visible + + + + 0 + 0 + 1 + + + + + odporucana_suma_garaz + + visible + + + + 0 + 0 + 1 + + + + + rovnake_miesto_garaz + + visible + + + + 0 + 0 + 1 + + + + + view_garaz_poistna_suma + + visible + + + + 0 + 0 + 1 + + + + + view_garaz_poistne + + visible + + + + 0 + 0 + 1 + + + + + hospodarska_budova + + visible + + + + 0 + 0 + 1 + + + + + hospodarska_budova_poistna_suma + + visible + + + + 0 + 0 + 1 + + + + + view_hospodarska_budova_poistne + + visible + + + + 0 + 0 + 1 + + + + + altanok + + visible + + + + 0 + 0 + 1 + + + + + altanok_suma + + visible + + + + 0 + 0 + 1 + + + + + view_altanok_poistne + + visible + + + + 0 + 0 + 1 + + + + + pristresok + + visible + + + + 0 + 0 + 1 + + + + + pristresok_suma + + visible + + + + 0 + 0 + 1 + + + + + view_pristresok_poistne + + visible + + + + 0 + 0 + 1 + + + + + chodnik + + visible + + + + 0 + 0 + 1 + + + + + chodnik_suma + + visible + + + + 0 + 0 + 1 + + + + + view_chodnik_poistne + + visible + + + + 0 + 0 + 1 + + + + + sauna + + visible + + + + 0 + 0 + 1 + + + + + sauna_suma + + visible + + + + 0 + 0 + 1 + + + + + view_sauna_poistne + + visible + + + + 0 + 0 + 1 + + + + + elektricka_brana + + visible + + + + 0 + 0 + 1 + + + + + elektricka_brana_suma + + visible + + + + 0 + 0 + 1 + + + + + view_brana_poistne + + visible + + + + 0 + 0 + 1 + + + + + tenisovy_kurt + + visible + + + + 0 + 0 + 1 + + + + + tenisovy_kurt_suma + + visible + + + + 0 + 0 + 1 + + + + + view_tenisovy_kurt_poistne + + visible + + + + 0 + 0 + 1 + + + + + bazen + + visible + + + + 0 + 0 + 1 + + + + + bazen_suma + + visible + + + + 0 + 0 + 1 + + + + + view_bazen_poistne + + visible + + + + 0 + 0 + 1 + + + + + studna + + visible + + + + 0 + 0 + 1 + + + + + studna_suma + + visible + + + + 0 + 0 + 1 + + + + + view_studna_poistne + + visible + + + + 0 + 0 + 1 + + + + + zumpa + + visible + + + + 0 + 0 + 1 + + + + + zumpa_suma + + visible + + + + 0 + 0 + 1 + + + + + view_zumpa_poistne + + visible + + + + 0 + 0 + 1 + + + + + ine + + visible + + + + 0 + 0 + 1 + + + + + ine_suma + + visible + + + + 0 + 0 + 1 + + + + + view_ine_stavby_poistne + + visible + + + + 0 + 0 + 1 + + + + + view_celkova_suma + + visible + + + + 0 + 0 + 1 + + + + + view_celkove_poistne + + visible + + + + 0 + 0 + 1 + + + + + 4 + + + + t2045 + 2237 + 841 + Údaje o zaplatení (view) + + agent + + true + + + + t2045_flex + + + variabilny_symbol + + visible + + + + 0 + 0 + 1 + + + + + 9 + + + + t2046 + 2237 + 929 + Informácie o províziach (view) + + agent + + true + + + + 10 + + + + t2484 + 1457 + 117 + Send mail + + + + t2729 + 2227 + 1021 + Sumár (view) + + agent + + true + + + + t2729_flex + + + odporucana_suma + + visible + + + + 0 + 0 + 1 + + + + + poistna_suma + + visible + + + + 0 + 0 + 1 + + + + + view_nehnutelnost_poistne + + visible + + + + 0 + 0 + 1 + + + + + view_nehnutelnost_celkove_poistne + + visible + + + + 0 + 0 + 1 + + + + + poistna_suma_odporucana + + visible + + + + 0 + 0 + 1 + + + + + poistna_suma_trvalo + + visible + + + + 0 + 0 + 1 + + + + + poistna_suma_docasne + + visible + + + + 0 + 0 + 1 + + + + + view_domacnost_poistne + + visible + + + + 0 + 0 + 1 + + + + + view_domacnost_celkove_poistne + + visible + + + + 0 + 0 + 1 + + + + + view_nehnutelnost_zodpovednost_poistne + + visible + + + + 0 + 0 + 1 + + + + + poistenie_zodpovednosti_clenov + + visible + + + + 0 + 0 + 1 + + + + + view_zodpovednost_celkove_poistne + + visible + + + + 0 + 0 + 1 + + + + + view_rocne_celkove_poistne + + visible + + + + 0 + 0 + 1 + + + + + periodicita_platby + + visible + + + + 0 + 0 + 1 + + + + + view_komplet_poistne + + visible + + + + 0 + 0 + 1 + + + + + zlava_za_ine_poistenie + + visible + + + + 0 + 0 + 1 + + + + + alarm_zlava + + visible + + + + 0 + 0 + 1 + + + + + obchodna_zlava + + visible + + + + 0 + 0 + 1 + + + + + akciova_zlava + + visible + + + + 0 + 0 + 1 + + + + + bezne_poistenie + + visible + + + + 0 + 0 + 1 + + + + + vyska_splatky + + visible + + + + 0 + 0 + 1 + + + + + cislo_zmluvy + + visible + + + + 0 + 0 + 1 + + + + + pdf_ponuka + + visible + + + + 0 + 0 + 1 + + + + + 7 + + + + t3 + 180 + 580 + Nehnuteľnosť a domácnosť + home weekend + + agent + + true + + + + t3_flex + + + dummy_data + + forbidden + + + dummy_data_get + + + + + + + + + 0 + 0 + 1 + + + + + 3 + + + + t332 + 1180 + 580 + Údaje o zmluve + + agent + + true + + + + t332_flex + + + cislo_zmluvy + + visible + + + + 0 + 0 + 1 + + + + + zaciatok_poistenia + + editable + true + + + + 0 + 0 + 1 + + + + + doba_urcita + + hidden + + + + 0 + 0 + 1 + + + + + koniec_poistenia + + hidden + + + + 0 + 0 + 1 + + + + + vinkulacia_v_prospech + + editable + + + + 0 + 0 + 1 + + + + + vinkulacia_cislo_zmluvy + + editable + + + + 0 + 0 + 1 + + + + + indexacia + + editable + + + + 0 + 0 + 1 + + + + + sposob_platenia + + editable + true + + + + 0 + 0 + 1 + + + + + povod_financii + + hidden + + + + 0 + 0 + 1 + + + + + osobitne_vyjadrenia + + editable + + + + 0 + 0 + 1 + + + + + poistnik_suhlas_gdpr + + editable + + + + 0 + 0 + 1 + + + + + pdf_zmluva + + visible + + + + 0 + 0 + 1 + + + + + 9 + + + + t363 + 620 + 700 + Domácnosť + + agent + + true + + + + t363_flex + + + typ_domacnosti + + editable + true + + + + 0 + 0 + 1 + + + + + poistenie_domacnosti_spoluucast + + editable + true + + + + 0 + 0 + 1 + + + + + zodpovednost_za_skodu + + editable + true + + + + 0 + 0 + 1 + + + + + uzemna_platnost + + hidden + + + + 0 + 0 + 1 + + + + + obyvanost_domacnosti + + editable + true + + + + 0 + 0 + 1 + + + + + celkova_podlahova_plocha + + editable + true + + + + 0 + 0 + 1 + + + + + alarm + + editable + true + + + + 0 + 0 + 1 + + + + + zaluzie_rolety + + editable + true + + + + 0 + 0 + 1 + + + + + 5 + + + + t364 + 620 + 1020 + Sumár + + agent + + true + + + + t364_flex + + + odporucana_suma + + hidden + + + + 0 + 0 + 1 + + + + + poistna_suma + + hidden + + + + 0 + 0 + 1 + + + + + view_nehnutelnost_poistne + + hidden + + + + 0 + 0 + 1 + + + + + view_nehnutelnost_celkove_poistne + + hidden + + + + 0 + 0 + 1 + + + + + poistna_suma_odporucana + + hidden + + + + 0 + 0 + 1 + + + + + poistna_suma_trvalo + + hidden + + + + 0 + 0 + 1 + + + + + poistna_suma_docasne + + hidden + + + + 0 + 0 + 1 + + + + + view_domacnost_poistne + + hidden + + + + 0 + 0 + 1 + + + + + view_domacnost_celkove_poistne + + hidden + + + + 0 + 0 + 1 + + + + + view_nehnutelnost_zodpovednost_poistne + + hidden + + + + 0 + 0 + 1 + + + + + poistenie_zodpovednosti_clenov + + hidden + + + + 0 + 0 + 1 + + + + + view_zodpovednost_celkove_poistne + + hidden + + + + 0 + 0 + 1 + + + + + view_rocne_celkove_poistne + + visible + + + + 0 + 0 + 1 + + + + + periodicita_platby + + editable + true + + + + 0 + 0 + 1 + + + + + view_komplet_poistne + + visible + + + + 0 + 0 + 1 + + + + + zlava_za_ine_poistenie + + editable + true + + + + 0 + 0 + 1 + + + + + alarm_zlava + + hidden + + + + 0 + 0 + 1 + + + + + obchodna_zlava + + editable + + + + 0 + 0 + 1 + + + + + akciova_zlava + + editable + + + + 0 + 0 + 1 + + + + + bezne_poistenie + + visible + + + + 0 + 0 + 1 + + + + + vyska_splatky + + visible + + + + 0 + 0 + 1 + + + + + cislo_zmluvy + + hidden + + + + 0 + 0 + 1 + + + + + pdf_ponuka + + visible + + + + 0 + 0 + 1 + + + + + 7 + + + + t4 + 180 + 900 + Iba domácnosť + weekend + + agent + + true + + + + t4_flex + + + dummy_data + + forbidden + + + dummy_data_get + + + + + + + + + 0 + 0 + 1 + + + + + 2 + + + + t413 + 620 + 540 + Vedľajšie stavby + + agent + + true + + + + t413_flex + + + hospodarska_budova + + editable + + + hospodarska_budova_set + + + + + + + + + 0 + 0 + 1 + + + + + hospodarska_budova_poistna_suma + + hidden + + + hospodarska_budova_poistna_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_hospodarska_budova_poistne + + hidden + + + + 0 + 0 + 1 + + + + + altanok + + editable + + + altanok_set + + + + + + + + + 0 + 0 + 1 + + + + + altanok_suma + + hidden + + + altanok_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_altanok_poistne + + hidden + + + + 0 + 0 + 1 + + + + + pristresok + + editable + + + pristresok_set + + + + + + + + + 0 + 0 + 1 + + + + + pristresok_suma + + hidden + + + pristresok_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_pristresok_poistne + + hidden + + + + 0 + 0 + 1 + + + + + chodnik + + editable + + + chodnik_set + + + + + + + + + 0 + 0 + 1 + + + + + chodnik_suma + + hidden + + + chodnik_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_chodnik_poistne + + hidden + + + + 0 + 0 + 1 + + + + + sauna + + editable + + + sauna_set + + + + + + + + + 0 + 0 + 1 + + + + + sauna_suma + + hidden + + + sauna_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_sauna_poistne + + hidden + + + + 0 + 0 + 1 + + + + + elektricka_brana + + editable + + + elektricka_brana_set + + + + + + + + + 0 + 0 + 1 + + + + + elektricka_brana_suma + + hidden + + + elektricka_brana_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_brana_poistne + + hidden + + + + 0 + 0 + 1 + + + + + tenisovy_kurt + + editable + + + tenisovy_kurt_set + + + + + + + + + 0 + 0 + 1 + + + + + tenisovy_kurt_suma + + hidden + + + tenisovy_kurt_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_tenisovy_kurt_poistne + + hidden + + + + 0 + 0 + 1 + + + + + bazen + + editable + + + bazen_set + + + + + + + + + 0 + 0 + 1 + + + + + bazen_suma + + hidden + + + bazen_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_bazen_poistne + + hidden + + + + 0 + 0 + 1 + + + + + studna + + editable + + + studna_set + + + + + + + + + 0 + 0 + 1 + + + + + studna_suma + + hidden + + + studna_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_studna_poistne + + hidden + + + + 0 + 0 + 1 + + + + + zumpa + + editable + + + zumpa_set + + + + + + + + + 0 + 0 + 1 + + + + + zumpa_suma + + hidden + + + zumpa_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_zumpa_poistne + + hidden + + + + 0 + 0 + 1 + + + + + ine + + editable + + + ine_set + + + + + + + + + 0 + 0 + 1 + + + + + ine_suma + + hidden + + + ine_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_ine_stavby_poistne + + hidden + + + + 0 + 0 + 1 + + + + + view_celkova_suma + + visible + + + + 0 + 0 + 1 + + + + + view_celkove_poistne + + visible + + + + 0 + 0 + 1 + + + + + 4 + + + + t414 + 620 + 380 + Doplnkové poistenie nehnuteľnosti + + agent + + true + + + + t414_flex + + + stavebne_materialy + + editable + + + stavebne_materialy_set + + + + + + + + + 0 + 0 + 1 + + + + + stavebne_materialy_suma + + hidden + + + + 0 + 0 + 1 + + + + + view_stavebne_materialy_poistne + + hidden + + + + 0 + 0 + 1 + + + + + stavebne_mechanizmy + + editable + + + stavebne_mechanizmy_set + + + + + + + + + 0 + 0 + 1 + + + + + stavebne_mechanizmy_suma + + hidden + + + + 0 + 0 + 1 + + + + + view_mechanizmy_poistne + + hidden + + + + 0 + 0 + 1 + + + + + garaz + + editable + + + garaz_set + + + + + + + + + 0 + 0 + 1 + + + + + podlahova_plocha_garaz + + hidden + + + + 0 + 0 + 1 + + + + + rovnake_miesto_garaz + + hidden + + + rovnake_miesto_garaz_set + + + + + + + + + 0 + 0 + 1 + + + + + odporucana_suma_garaz + + hidden + + + + 0 + 0 + 1 + + + + + view_garaz_poistna_suma + + hidden + + + + 0 + 0 + 1 + + + + + view_garaz_poistne + + hidden + + + + 0 + 0 + 1 + + + + + 3 + + + + t421 + 620 + 860 + Doplnkové poistenie domácnosti + + agent + + true + + + + t421_flex + + + cennosti + + editable + + + cennosti_set + + + + + + + + + 0 + 0 + 1 + + + + + cennosti_suma + + hidden + + + cennosti_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_cennosti_poistne + + hidden + + + + 0 + 0 + 1 + + + + + umelecke_diela + + editable + + + umelecke_diela_set + + + + + + + + + 0 + 0 + 1 + + + + + umelecke_diela_suma + + hidden + + + umelecke_diela_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_umelecke_deial_poistne + + hidden + + + + 0 + 0 + 1 + + + + + elektronika + + editable + + + elektronika_set + + + + + + + + + 0 + 0 + 1 + + + + + elektronika_suma + + hidden + + + elektronika_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_optika_poistne + + hidden + + + + 0 + 0 + 1 + + + + + presklenie + + editable + + + presklenie_set + + + + + + + + + 0 + 0 + 1 + + + + + presklenie_suma + + hidden + + + presklenie_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_presklenie_poistne + + hidden + + + + 0 + 0 + 1 + + + + + zahradny_nabytok + + editable + + + zahradny_nabytok_set + + + + + + + + + 0 + 0 + 1 + + + + + zahradny_nabytok_suma + + hidden + + + zahradny_nabytok_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_zahradny_nabytok_poistne + + hidden + + + + 0 + 0 + 1 + + + + + elektromotory + + editable + + + elektromotory_set + + + + + + + + + 0 + 0 + 1 + + + + + elektromotory_suma + + hidden + + + elektromotory_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_elektromotory_poistne + + hidden + + + + 0 + 0 + 1 + + + + + stavebne_sucasti + + editable + + + stavebne_sucasti_set + + + + + + + + + 0 + 0 + 1 + + + + + stavebne_sucasti_suma + + hidden + + + stavebne_sucasti_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_stavebne_sucasti_poistne + + hidden + + + + 0 + 0 + 1 + + + + + sportove_naradie + + editable + + + sportove_naradie_set + + + + + + + + + 0 + 0 + 1 + + + + + sportove_naradie_suma + + hidden + + + sportove_naradie_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_sportove_naradie_poistne + + hidden + + + + 0 + 0 + 1 + + + + + ine_domacnost + + editable + + + ine_domacnost_set + + + + + + + + + 0 + 0 + 1 + + + + + ine_domacnost_suma + + hidden + + + ine_domacnost_suma_set + + + + + + + + + 0 + 0 + 1 + + + + + view_ine_poistne + + hidden + + + + 0 + 0 + 1 + + + + + celkova_poistna_suma + + visible + + + + 0 + 0 + 1 + + + + + celkove_poistne + + visible + + + + 0 + 0 + 1 + + + + + 6 + + + + t588 + 620 + 1180 + Údaje o poistníkovi a mieste poistenia + + agent + + true + + + + t588_flex + + + poistnik_typ + + editable + + + + 0 + 0 + 1 + + + + + poistnik_ico + + hidden + + + + 0 + 0 + 1 + + + + + poistnik_obchodne_meno + + hidden + + + + 0 + 0 + 1 + + + + + poistnik_v_zastupeni + + hidden + + + + 0 + 0 + 1 + + + + + poistnik_konatel + + hidden + + + + 0 + 0 + 1 + + + + + poistnik_titul_pred + + editable + + + + 0 + 0 + 1 + + + + + poistnik_titul_za + + editable + + + + 0 + 0 + 1 + + + + + poistnik_meno + + editable + true + + + + 0 + 0 + 1 + + + + + poistnik_priezvisko + + editable + true + + + + 0 + 0 + 1 + + + + + poistnik_preukaz + + editable + true + + + + 0 + 0 + 1 + + + + + poistnik_preukaz_cislo + + editable + true + + + + 0 + 0 + 1 + + + + + poistnik_statna_prislusnost + + editable + true + + + + 0 + 0 + 1 + + + + + poistnik_datum_narodenia + + editable + true + + + + 0 + 0 + 1 + + + + + poistnik_rodne_cislo + + editable + true + + + + 0 + 0 + 1 + + + + + poistnik_telefon + + editable + + + + 0 + 0 + 1 + + + + + poistnik_email + + editable + true + + + + 0 + 0 + 1 + + + + + poisteny_ina_osoba + + editable + + + + 0 + 0 + 1 + + + + + poisteny_typ + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_ico + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_obchodne_meno + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_v_zastupeni + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_konatel + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_titul_pred + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_titul_za + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_meno + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_priezvisko + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_preukaz + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_preukaz_cislo + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_statna_prislusnost + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_datum_narodenia + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_rodne_cislo + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_telefon + + hidden + + + + 0 + 0 + 1 + + + + + poisteny_email + + hidden + + + + 0 + 0 + 1 + + + + + miesto_poistenia_ulica + + editable + true + + + + 0 + 0 + 1 + + + + + miesto_poistenia_cislo + + editable + true + + + + 0 + 0 + 1 + + + + + miesto_poistenia_psc + + editable + true + + + + 0 + 0 + 1 + + + + + miesto_poistenia_obec + + editable + true + + + + 0 + 0 + 1 + + + + + trvaly_pobyt_rovnaky + + editable + + + + 0 + 0 + 1 + + + + + trvaly_pobyt_ulica + + hidden + + + + 0 + 0 + 1 + + + + + trvaly_pobyt_cislo + + hidden + + + + 0 + 0 + 1 + + + + + trvaly_pobyt_psc + + hidden + + + + 0 + 0 + 1 + + + + + trvaly_pobyt_obec + + hidden + + + + 0 + 0 + 1 + + + + + korespondencna_rovnaka + + editable + + + + 0 + 0 + 1 + + + + + korespondencna_ulica + + hidden + + + + 0 + 0 + 1 + + + + + korespondencna_cislo + + hidden + + + + 0 + 0 + 1 + + + + + korespondencna_psc + + hidden + + + + 0 + 0 + 1 + + + + + korespondencna_obec + + hidden + + + + 0 + 0 + 1 + + + + + garaz_ulica + + hidden + + + + 0 + 0 + 1 + + + + + garaz_cislo + + hidden + + + + 0 + 0 + 1 + + + + + garaz_psc + + hidden + + + + 0 + 0 + 1 + + + + + garaz_obec + + hidden + + + + 0 + 0 + 1 + + + + + 8 + + + + t674 + 1433 + 965 + Zrušenie návrhu poistky (po vypršaní lehoty) + + 11 + + + + t680 + 1681 + 967 + Napárovanie platby + + company + + true + + + + t680_flex + + + cislo_zmluvy + + forbidden + true + + + + 0 + 0 + 1 + + + + + poistnik_meno + + visible + true + + + + 0 + 0 + 1 + + + + + poistnik_priezvisko + + visible + true + + + + 0 + 0 + 1 + + + + + zaciatok_poistenia + + visible + true + + + + 0 + 0 + 1 + + + + + datum_valuty + + editable + + + + 0 + 0 + 1 + + + + + predcislo_uctu + + editable + + + + 0 + 0 + 1 + + + + + cislo_uctu + + editable + true + + + + 0 + 0 + 1 + + + + + predcislo_protiuctu + + editable + + + + 0 + 0 + 1 + + + + + cislo_protiuctu + + editable + + + + 0 + 0 + 1 + + + + + kod_banky_protiuctu + + editable + + + + 0 + 0 + 1 + + + + + nazov_protiuctu + + editable + + + + 0 + 0 + 1 + + + + + suma + + editable + true + + + + 0 + 0 + 1 + + + + + mena + + editable + true + + + + 0 + 0 + 1 + + + + + kurz + + editable + + + + 0 + 0 + 1 + + + + + zostatok + + editable + true + + + + 0 + 0 + 1 + + + + + popis_obratu + + editable + + + + 0 + 0 + 1 + + + + + e2e_reference + + editable + + + + 0 + 0 + 1 + + + + + variabilny_symbol + + editable + + + + 0 + 0 + 1 + + + + + konstantny_symbol + + editable + + + + 0 + 0 + 1 + + + + + specificky_symbol + + editable + + + + 0 + 0 + 1 + + + + + poznamka + + editable + + + + 0 + 0 + 1 + + + + + cislo_vypisu + + editable + + + + 0 + 0 + 1 + + + + + id_protiuctu_1 + + editable + + + + 0 + 0 + 1 + + + + + id_protiuctu_2 + + editable + + + + 0 + 0 + 1 + + + + + id_protiuctu_3 + + editable + + + + 0 + 0 + 1 + + + + + id_protiuctu_4 + + editable + + + + 0 + 0 + 1 + + + + + sprava_prijimatelovi_1 + + editable + + + + 0 + 0 + 1 + + + + + sprava_prijimatelovi_2 + + editable + + + + 0 + 0 + 1 + + + + + sprava_prijimatelovi_3 + + editable + + + + 0 + 0 + 1 + + + + + sprava_prijimatelovi_4 + + editable + + + + 0 + 0 + 1 + + + + + 12 + + + + t686 + 1870 + 1071 + Aktívna zmluva + + 13 + + + + t687 + 1431 + 1243 + Expirovaný návrh poistky + + 12 + + + + t692 + 1682 + 1250 + Expirácia zmluvy + + 14 + + + + t694 + 2077 + 1245 + Expirovaná zmluva + + 15 + + + + p1 + 20 + 580 + 1 + 1 + + + p1368 + 900 + 380 + Doplnkové poistenie nehnuteľnosti finished + 0 + + + p1369 + 900 + 540 + Vedľajšie stavby finished + 0 + + + p1372 + 900 + 860 + Doplnkové poistenie domácnosti finished + 0 + + + p1393 + 900 + 1020 + Sumár finished + 0 + + + p1601 + 540 + 300 + 15 + 0 + + + p1607 + 540 + 460 + 16 + 0 + + + p1612 + 540 + 140 + 14 + 0 + + + p1626 + 540 + 620 + 17 + 0 + + + p1628 + 180 + 140 + 2 + 0 + + + p1673 + 540 + 940 + 19 + 0 + + + p1677 + 540 + 780 + 18 + 0 + + + p1689 + 540 + 1100 + 20 + 0 + + + p1851 + 180 + 1180 + 3 + 0 + + + p2047 + 2063 + 43 + 0 + + + p2048 + 2069 + 146 + 0 + + + p2049 + 2069 + 250 + 0 + + + p2050 + 2071 + 350 + 0 + + + p2051 + 2065 + 450 + 0 + + + p2052 + 2069 + 554 + 0 + + + p2053 + 2071 + 651 + 0 + + + p2054 + 2073 + 746 + 0 + + + p2055 + 2073 + 837 + 0 + + + p2056 + 2070 + 927 + 0 + + + p2280 + 715 + 615 + 0 + + + p2284 + 782 + 931 + 0 + + + p2480 + 1399 + 117 + 0 + + + p2728 + 2067 + 1013 + 0 + + + p398 + 420 + 60 + 5 + 0 + + + p399 + 420 + 220 + 6 + 0 + + + p400 + 420 + 700 + 9 + 0 + + + p402 + 420 + 1020 + 11 + 0 + + + p415 + 420 + 540 + 8 + 0 + + + p416 + 420 + 380 + 7 + 0 + + + p422 + 420 + 860 + 10 + 0 + + + p444 + 860 + 60 + Základné informácie finished + 0 + + + p445 + 860 + 220 + Nehnuteľnosť finished + 0 + + + p446 + 900 + 700 + Domácnosť finished + 0 + + + p589 + 420 + 1180 + 12 + 0 + + + p594 + 900 + 1180 + Údaje o poistníkovi a mieste poistenia finished + 0 + + + p633 + 260 + 60 + 4 + 0 + + + p672 + 1530 + 585 + 22 + 0 + + + p682 + 1681 + 1070 + 23 + 0 + + + p683 + 1430 + 1071 + 24 + 0 + + + p693 + 1862 + 1249 + 25 + 0 + + + a12 + regular + p1 + t4 + 1 + + + a1373 + regular + t414 + p1368 + 1 + + + a1374 + regular + t413 + p1369 + 1 + + + a1394 + regular + t364 + p1393 + 1 + + + a1397 + regular + t421 + p1372 + 1 + + + a1400 + regular + p1372 + t332 + 1 + + + a1595 + regular + p445 + t332 + 1 + + + a1596 + reset + p445 + t155 + 1 + + + a1599 + reset + p1368 + t414 + 1 + + + a1600 + reset + p1369 + t413 + 1 + + + a1602 + regular + t155 + p1601 + 1 + + + a1603 + regular + p1601 + t414 + 1 + + + a1604 + regular + t414 + p1601 + 1 + + + a1605 + regular + t2 + p416 + 1 + + + a1606 + regular + t2 + p415 + 1 + + + a1608 + regular + t414 + p1607 + 1 + + + a1609 + regular + p1607 + t413 + 1 + + + a1610 + regular + t413 + p1607 + 1 + + + a1611 + regular + p444 + t332 + 1 + + + a1613 + regular + t154 + p1612 + 1 + + + a1614 + regular + p1612 + t155 + 1 + + + a1615 + regular + t155 + p1612 + 1 + + + a1616 + regular + p1368 + t332 + 1 + + + a1617 + regular + p1369 + t332 + 1 + + + a1619 + regular + p444 + t1618 + 1 + + + a1620 + regular + p445 + t1618 + 1 + + + a1621 + regular + p1368 + t1618 + 1 + + + a1622 + regular + p1369 + t1618 + 1 + + + a1623 + regular + p1393 + t1618 + 1 + + + a1625 + regular + p594 + t1618 + 1 + + + a1627 + regular + t413 + p1626 + 1 + + + a1630 + reset + p444 + t154 + 1 + + + a1640 + regular + t2 + p589 + 1 + + + a1641 + regular + p398 + t1618 + 1 + + + a1642 + regular + p399 + t1618 + 1 + + + a1643 + regular + p416 + t1618 + 1 + + + a1644 + regular + p415 + t1618 + 1 + + + a1645 + regular + p633 + t1618 + 1 + + + a1646 + regular + p402 + t1618 + 1 + + + a1648 + regular + p589 + t1618 + 1 + + + a1649 + reset + p1393 + t364 + 1 + + + a1651 + reset + p594 + t588 + 1 + + + a1657 + regular + t332 + p672 + 1 + + + a1660 + regular + t1618 + p672 + 1 + + + a1662 + regular + t3 + p589 + 1 + + + a1669 + regular + t3 + p1628 + 1 + + + a1670 + regular + t2 + p1628 + 1 + + + a1671 + regular + p1628 + t155 + 1 + + + a1672 + regular + t155 + p1628 + 1 + + + a1674 + regular + t2 + p1673 + 1 + + + a1675 + regular + p1673 + t364 + 1 + + + a1676 + regular + t364 + p1673 + 1 + + + a1678 + regular + t363 + p1677 + 1 + + + a1679 + regular + p1677 + t421 + 1 + + + a1680 + regular + t421 + p1677 + 1 + + + a1685 + regular + t421 + p1673 + 1 + + + a1686 + regular + p1626 + t363 + 1 + + + a1687 + regular + t363 + p1626 + 1 + + + a1688 + regular + t4 + p1626 + 1 + + + a1690 + regular + t364 + p1689 + 1 + + + a1691 + regular + p1689 + t588 + 1 + + + a1692 + regular + t588 + p1689 + 1 + + + a1693 + regular + p1393 + t332 + 1 + + + a1694 + regular + p594 + t332 + 1 + + + a1696 + reset + p446 + t363 + 1 + + + a1697 + reset + p1372 + t421 + 1 + + + a1698 + regular + p589 + t332 + 1 + + + a1702 + regular + t4 + p589 + 1 + + + a1704 + regular + p444 + t1661 + 1 + + + a1705 + regular + p446 + t1661 + 1 + + + a1706 + regular + p1372 + t1661 + 1 + + + a1707 + regular + p1393 + t1661 + 1 + + + a1708 + regular + p594 + t1661 + 1 + + + a1710 + regular + p398 + t1661 + 1 + + + a1711 + regular + p400 + t1661 + 1 + + + a1712 + regular + p422 + t1661 + 1 + + + a1713 + regular + p402 + t1661 + 1 + + + a1714 + regular + p589 + t1661 + 1 + + + a1716 + regular + t1661 + p672 + 1 + + + a1852 + regular + t4 + p1851 + 1 + + + a1853 + regular + p1851 + t1661 + 1 + + + a2010 + regular + p398 + t332 + 1 + + + a2011 + regular + p399 + t332 + 1 + + + a2012 + regular + p416 + t332 + 1 + + + a2013 + regular + p415 + t332 + 1 + + + a2057 + regular + t1618 + p2047 + 1 + + + a2058 + regular + t1618 + p2048 + 1 + + + a2059 + regular + t1618 + p2049 + 1 + + + a2060 + regular + t1618 + p2050 + 1 + + + a2061 + regular + t1618 + p2051 + 1 + + + a2062 + regular + t1618 + p2052 + 1 + + + a2063 + regular + t1618 + p2053 + 1 + + + a2064 + regular + t1618 + p2054 + 1 + + + a2065 + regular + t1618 + p2055 + 1 + + + a2066 + regular + t1618 + p2056 + 1 + + + a2067 + regular + t1661 + p2056 + 1 + + + a2068 + regular + t1661 + p2055 + 1 + + + a2069 + regular + t1661 + p2054 + 1 + + + a2070 + regular + t1661 + p2053 + 1 + + + a2071 + regular + t1661 + p2052 + 1 + + + a2072 + regular + t1661 + p2051 + 1 + + + a2073 + regular + t1661 + p2050 + 1 + + + a2074 + regular + t1661 + p2049 + 1 + + + a2075 + regular + t1661 + p2048 + 1 + + + a2076 + regular + t1661 + p2047 + 1 + + + a2077 + regular + p2047 + t2015 + 1 + + + a2078 + regular + t2015 + p2047 + 1 + + + a2079 + regular + p2048 + t2019 + 1 + + + a2080 + regular + t2019 + p2048 + 1 + + + a2081 + regular + p2049 + t2020 + 1 + + + a2082 + regular + t2020 + p2049 + 1 + + + a2083 + regular + p2050 + t2021 + 1 + + + a2084 + regular + t2021 + p2050 + 1 + + + a2085 + regular + p2051 + t2018 + 1 + + + a2086 + regular + t2018 + p2051 + 1 + + + a2087 + regular + p2052 + t2017 + 1 + + + a2088 + regular + t2017 + p2052 + 1 + + + a2089 + regular + p2053 + t2016 + 1 + + + a2090 + regular + t2016 + p2053 + 1 + + + a2091 + regular + p2054 + t2014 + 1 + + + a2092 + regular + t2014 + p2054 + 1 + + + a2093 + regular + p2055 + t2045 + 1 + + + a2094 + regular + t2045 + p2055 + 1 + + + a2095 + regular + p2056 + t2046 + 1 + + + a2096 + regular + t2046 + p2056 + 1 + + + a2097 + regular + t332 + p2047 + 1 + + + a2098 + regular + t332 + p2048 + 1 + + + a2099 + regular + t332 + p2049 + 1 + + + a2100 + regular + t332 + p2050 + 1 + + + a2101 + regular + t332 + p2051 + 1 + + + a2102 + regular + t332 + p2052 + 1 + + + a2103 + regular + t332 + p2053 + 1 + + + a2104 + regular + t332 + p2054 + 1 + + + a2105 + regular + t332 + p2055 + 1 + + + a2106 + regular + t332 + p2056 + 1 + + + a2281 + regular + t154 + p2280 + 1 + + + a2282 + regular + p2280 + t363 + 1 + + + a2283 + regular + t363 + p2280 + 1 + + + a2285 + regular + t413 + p2284 + 1 + + + a2286 + regular + p2284 + t364 + 1 + + + a2287 + regular + t364 + p2284 + 1 + + + a2479 + regular + t363 + p2284 + 1 + + + a2481 + regular + t1618 + p2480 + 1 + + + a2482 + regular + t332 + p2480 + 1 + + + a2483 + regular + t1661 + p2480 + 1 + + + a2485 + regular + p2480 + t2484 + 1 + + + a2730 + regular + p2728 + t2729 + 1 + + + a2731 + regular + t2729 + p2728 + 1 + + + a2732 + regular + t1618 + p2728 + 1 + + + a2733 + regular + t332 + p2728 + 1 + + + a2734 + regular + t1661 + p2728 + 1 + + + a403 + regular + p398 + t154 + 1 + + + a404 + regular + t154 + p398 + 1 + + + a405 + regular + p399 + t155 + 1 + + + a406 + regular + t155 + p399 + 1 + + + a407 + regular + p400 + t363 + 1 + + + a408 + regular + t363 + p400 + 1 + + + a411 + regular + p402 + t364 + 1 + + + a412 + regular + t364 + p402 + 1 + + + a417 + regular + p415 + t413 + 1 + + + a418 + regular + t413 + p415 + 1 + + + a419 + regular + p416 + t414 + 1 + + + a420 + regular + t414 + p416 + 1 + + + a423 + regular + p422 + t421 + 1 + + + a424 + regular + t421 + p422 + 1 + + + a425 + regular + t2 + p398 + 1 + + + a426 + regular + t3 + p398 + 1 + + + a427 + regular + t4 + p398 + 1 + + + a428 + regular + t2 + p399 + 1 + + + a429 + regular + t3 + p399 + 1 + + + a430 + regular + t3 + p400 + 1 + + + a431 + regular + t4 + p400 + 1 + + + a435 + regular + t3 + p402 + 1 + + + a436 + regular + t4 + p402 + 1 + + + a437 + regular + t2 + p402 + 1 + + + a439 + regular + t3 + p415 + 1 + + + a441 + regular + t3 + p416 + 1 + + + a442 + regular + t4 + p422 + 1 + + + a443 + regular + t3 + p422 + 1 + + + a452 + regular + t154 + p444 + 1 + + + a453 + regular + t155 + p445 + 1 + + + a454 + regular + t363 + p446 + 1 + + + a514 + regular + p402 + t332 + 1 + + + a516 + regular + p400 + t332 + 1 + + + a517 + regular + p422 + t332 + 1 + + + a535 + regular + p446 + t332 + 1 + + + a591 + regular + p589 + t588 + 1 + + + a592 + regular + t588 + p589 + 1 + + + a595 + regular + t588 + p594 + 1 + + + a634 + regular + t2 + p633 + 1 + + + a677 + regular + p672 + t674 + 1 + + + a681 + regular + p672 + t680 + 1 + + + a684 + regular + t674 + p683 + 1 + + + a685 + regular + t680 + p682 + 1 + + + a688 + regular + p683 + t687 + 1 + + + a689 + regular + t687 + p683 + 1 + + + a690 + regular + p682 + t686 + 1 + + + a691 + regular + t686 + p682 + 1 + + + a695 + regular + p682 + t692 + 1 + + + a696 + regular + t692 + p693 + 1 + + + a697 + regular + p693 + t694 + 1 + + + a698 + regular + t694 + p693 + 1 + + + a7 + regular + p1 + t2 + 1 + + + a9 + regular + p1 + t3 + 1 + + diff --git a/src/test/resources/invalid_data_ref_layout.xml b/src/test/resources/invalid_data_ref_layout.xml deleted file mode 100644 index e438bc9371c..00000000000 --- a/src/test/resources/invalid_data_ref_layout.xml +++ /dev/null @@ -1,50 +0,0 @@ - - invalid_data_ref_layout - IDR - Invalid data ref in grid layout - device_hub - true - true - false - - text_0 - Text field - Text field with layout - - - text_1 - Text field - Text field without layout - - - t1 - 500 - 180 - - diff --git a/src/test/resources/ipc_bulk.xml b/src/test/resources/ipc_bulk.xml index 11a6eac4416..e5abcdec0e8 100644 --- a/src/test/resources/ipc_bulk.xml +++ b/src/test/resources/ipc_bulk.xml @@ -1,10 +1,15 @@ - - + test - TST + 1.0.0 Test true + false + + TST + + + field Field @@ -14,18 +19,18 @@ task 0 0 - + Task - 1 + task1 - - + + - + ]]> + @@ -33,6 +38,6 @@ work_task 0 0 - + Work task - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/ipc_createCase.xml b/src/test/resources/ipc_createCase.xml index b78a5f1deef..978b662162e 100644 --- a/src/test/resources/ipc_createCase.xml +++ b/src/test/resources/ipc_createCase.xml @@ -1,10 +1,15 @@ - - + create_case_net - TST + 1.0.0 Test true + false + + TST + + + field Field @@ -19,14 +24,16 @@ task 0 0 - + Task - 1 + t1 - + + + ]]> + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/ipc_data.xml b/src/test/resources/ipc_data.xml index 97112eb7e4e..05bce831a79 100644 --- a/src/test/resources/ipc_data.xml +++ b/src/test/resources/ipc_data.xml @@ -1,92 +1,105 @@ - - + test - TST + 1.0.0 Test - - - data_text - Text - + false + false + + TST + + + data_number Number - + + data_text + Text + - 2 + t2 380 180 - - - data_text - - visible - - - - data_number - - visible - - + Enabled + + t2_flex + + + data_text + + visible + + + + 0 + 0 + 1 + + + + + data_number + + visible + + + + 0 + 0 + 1 + + + - 2_assign + t2_assign - - - text: f.data_text, - number: f.data_number; + + - + ]]> + - 3 + t3 380 340 - + Disabled - - 1 + p1 220 180 - 1 - false - 5 + p5 220 340 - 0 - false - - 4 + a4 regular - 1 - 2 + p1 + t2 1 - 6 + a6 regular - 5 - 3 + p5 + t3 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/ipc_set_data.xml b/src/test/resources/ipc_set_data.xml index dee4622499c..678be584bdd 100644 --- a/src/test/resources/ipc_set_data.xml +++ b/src/test/resources/ipc_set_data.xml @@ -1,68 +1,83 @@ - - + test - TST + 1.0.0 Test - - - data_text - Text - + false + false + + TST + + + data_number Number - + + data_text + Text + - 2 + t2 380 180 - - - data_text - - visible - - - - data_number - - visible - - + Enabled + + t2_flex + + + data_text + + visible + + + + 0 + 0 + 1 + + + + + data_number + + visible + + + + 0 + 0 + 1 + + + - 2_assign + t2_assign - - - text: f.data_text, - number: f.data_number; + + - + ]]> + - - 1 + p1 220 180 - 1 - false - - 4 + a4 regular - 1 - 2 + p1 + t2 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/ipc_where.xml b/src/test/resources/ipc_where.xml index 7122364826e..7812912204b 100644 --- a/src/test/resources/ipc_where.xml +++ b/src/test/resources/ipc_where.xml @@ -1,18 +1,23 @@ - - + test - TST + 1.0.0 Test true + false + + TST + + + - field - Field + count + Count 0 - count - Count + field + Field 0 @@ -20,57 +25,50 @@ Paged 0 + + synchronized + 0 + 0 + Synchronized + task 0 0 - + Task - 1 + t1 - - - field: f.field; + + - - - - field: f.field; + ]]> + + + - - - - field: f.count; - + ]]> + + + - - - - field: f.paged; - + change count value { return cases.size(); } + ]]> + + + - + change paged value { return cases.size(); } + ]]> + - - synchronized - 0 - 0 - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/mapping_test.xml b/src/test/resources/mapping_test.xml deleted file mode 100755 index d7ab7541dd6..00000000000 --- a/src/test/resources/mapping_test.xml +++ /dev/null @@ -1,901 +0,0 @@ - - - test - TST - Test - false - - - 1 - Agent - - - 2 - System - - - - 1 - On which date would you like your cover to start? - - - 2 - City - true - - - 5 - Property type - Flat - House - Townhouse - Other - - - 11 - Do you own or rent the property? - Mortgaged - Owned - Rented - - - 14 - What are the external walls built with? - Brick - Concrete - Timber - - - 18 - Size of living area - - - 20 - How much would it cost to replace the entire contents of your home as new? - - - - 22 - Would you like to insure any individual items? - Television - Computer - Home cinema - - - 24 - Locks on your property - 5 lever mortice deadlock - 5 lever mortice deadlock to British Standard BS3621 - Rim automatic deadlatch with key - Other type of lock - - - 25 - Is a burglar alarm fitted and used? - - - 27 - Property owner - 1 - - - 29 - How many adults 18 or over live in the property - - - 30 - How many children under 18 live in the property - - - 38 - Quote - - - - 1 - 2 - - 1 - - true - - - - - 2 - 3 - - 1 - - true - - - - - 3 - 4 - - 1 - - true - - - - - 4 - 14 - - 1 - - true - - - - 5 - - editable - required - - - - 11 - - editable - - - - 14 - - editable - - - - 18 - - editable - - - - - 5 - 15 - - 1 - - true - - - - 20 - - editable - required - - - - 22 - - editable - - - - 24 - - editable - - - - 25 - - editable - - - - - 6 - 27 - - 2 - - true - - - - 1 - - visible - - - - 2 - - visible - - - - 27 - - visible - - - - 29 - - visible - - - - 30 - - visible - - - - 5 - - visible - - - - 11 - - visible - - - - 14 - - visible - - - - 18 - - visible - - - - 20 - - visible - - - - 22 - - visible - - - - 24 - - visible - - - - 25 - - visible - - - - 38 - - editable - required - - - - - 7 - 30 - - 2 - - true - - - - 1 - - visible - - - - 2 - - visible - - - - 27 - - visible - - - - 29 - - visible - - - - 30 - - visible - - - - 5 - - visible - - - - 11 - - visible - - - - 14 - - visible - - - - 18 - - visible - - - - 38 - - editable - required - - - - - 8 - 33 - - 2 - - true - - - - 1 - - visible - - - - 2 - - visible - - - - 27 - - visible - - - - 29 - - visible - - - - 30 - - visible - - - - 20 - - visible - - - - 22 - - visible - - - - 24 - - visible - - - - 25 - - visible - - - - 38 - - editable - required - - - - - 9 - 36 - - 1 - - true - - - - - 10 - 49 - - 2 - - true - - - - - 11 - 96 - - 1 - - true - - - - 1 - - editable - required - - - - 2 - - editable - - - - 27 - - editable - - - - 29 - - editable - - - - 30 - - editable - - - - - - Dátum začiatku poistenia - - - - 2 - 300 - 140 - - - - 3 - 300 - 260 - - - - 4 - 300 - 380 - - - - 14 - 620 - 140 - - - - 15 - 620 - 380 - - - - 27 - 940 - 260 - - - - 30 - 940 - 140 - - - - 33 - 940 - 380 - - - - 36 - 1260 - 180 - - - - 49 - 1260 - 340 - - - - 96 - 620 - 260 - - - - - 1 - 140 - 260 - - 1 - false - - - 5 - 460 - 140 - - 0 - false - - - 6 - 460 - 380 - - 0 - false - - - 19 - 940 - 20 - - 0 - false - - - 21 - 940 - 500 - - 0 - false - - - 23 - 780 - 140 - - 0 - false - - - 24 - 780 - 380 - - 0 - false - - - 37 - 1100 - 260 - - 0 - false - - - 42 - 1420 - 260 - - 0 - false - - - 53 - 780 - 260 - - 0 - false - - - 59 - 460 - 260 - - 0 - false - - - - 7 - regular - 1 - 2 - 1 - - - 8 - regular - 2 - 5 - 1 - - - 9 - regular - 1 - 3 - 1 - - - 10 - regular - 3 - 5 - 1 - - - 11 - regular - 3 - 6 - 1 - - - 12 - regular - 1 - 4 - 1 - - - 13 - regular - 4 - 6 - 1 - - - 17 - regular - 5 - 14 - 1 - - - 18 - regular - 6 - 15 - 1 - - - 20 - regular - 2 - 19 - 1 - - 300 - 20 - - - - 22 - regular - 4 - 21 - 1 - - 300 - 500 - - - - 25 - regular - 14 - 23 - 1 - - - 26 - regular - 15 - 24 - 1 - - - 28 - regular - 23 - 27 - 1 - - - 29 - regular - 24 - 27 - 1 - - - 31 - regular - 23 - 30 - 1 - - - 32 - regular - 19 - 30 - 1 - - - 34 - regular - 24 - 33 - 1 - - - 35 - regular - 21 - 33 - 1 - - - 38 - regular - 30 - 37 - 1 - - - 39 - regular - 27 - 37 - 1 - - - 40 - regular - 33 - 37 - 1 - - - 41 - regular - 37 - 36 - 1 - - - 43 - regular - 36 - 42 - 1 - - - 50 - regular - 37 - 49 - 1 - - - 56 - regular - 53 - 30 - 1 - - - 57 - regular - 53 - 27 - 1 - - - 58 - regular - 53 - 33 - 1 - - - 60 - regular - 2 - 59 - 1 - - - 61 - regular - 3 - 59 - 1 - - - 62 - regular - 4 - 59 - 1 - - - 104 - regular - 59 - 96 - 1 - - - 105 - regular - 96 - 53 - 1 - - - 147 - regular - 49 - 42 - 1 - - \ No newline at end of file diff --git a/src/test/resources/net_clone.xml b/src/test/resources/net_clone.xml index 31c6e185104..2f3e94d4be9 100644 --- a/src/test/resources/net_clone.xml +++ b/src/test/resources/net_clone.xml @@ -1,76 +1,79 @@ - - + test - TST + 1.0.0 Test - - user - User - + false + false + + TST + + + admin Admin - + + identity + Identity + - 2 + t2 620 260 - + + <flex> + <id>t2_flex</id> + </flex> </transition> - <!-- PLACES --> <place> - <id>1</id> + <id>p1</id> <x>380</x> <y>260</y> - <label></label> <tokens>0</tokens> - <static>false</static> </place> - <!-- ARCS --> <arc> - <id>3</id> + <id>a3</id> <type>regular</type> - <sourceId>1</sourceId> - <destinationId>2</destinationId> + <sourceId>p1</sourceId> + <destinationId>t2</destinationId> <multiplicity>1</multiplicity> - <breakPoint> + <breakpoint> <x>500</x> <y>220</y> - </breakPoint> + </breakpoint> </arc> <arc> - <id>4</id> + <id>a4</id> <type>reset</type> - <sourceId>1</sourceId> - <destinationId>2</destinationId> + <sourceId>p1</sourceId> + <destinationId>t2</destinationId> <multiplicity>1</multiplicity> - <breakPoint> + <breakpoint> <x>500</x> <y>180</y> - </breakPoint> + </breakpoint> </arc> <arc> - <id>5</id> + <id>a5</id> <type>inhibitor</type> - <sourceId>1</sourceId> - <destinationId>2</destinationId> + <sourceId>p1</sourceId> + <destinationId>t2</destinationId> <multiplicity>1</multiplicity> - <breakPoint> + <breakpoint> <x>500</x> <y>300</y> - </breakPoint> + </breakpoint> </arc> <arc> - <id>6</id> + <id>a6</id> <type>read</type> - <sourceId>1</sourceId> - <destinationId>2</destinationId> + <sourceId>p1</sourceId> + <destinationId>t2</destinationId> <multiplicity>1</multiplicity> - <breakPoint> + <breakpoint> <x>500</x> <y>340</y> - </breakPoint> + </breakpoint> </arc> -</document> \ No newline at end of file +</process> \ No newline at end of file diff --git a/src/test/resources/net_import_1.xml b/src/test/resources/net_import_1.xml index 1b6eb07a99b..3859f047f81 100644 --- a/src/test/resources/net_import_1.xml +++ b/src/test/resources/net_import_1.xml @@ -1,15 +1,14 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../main/resources/petriNets/petriflow_schema.xsd"> <id>new_model</id> <version>1.0.0</version> - <initials>NEW</initials> <title>New Model home - true - false - - + false + false + + NEW + newRole_1 newRole_1 @@ -18,7 +17,6 @@ newRole_2 newRole_2 - newVariable_1 newVariable_1 @@ -39,20 +37,22 @@ newVariable_5 newVariable_5 - - - 1 + t1 481 186 - + task1 + + t1_flex + - 2 + t2 481 186 - + task2 + + t2_flex + - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/net_import_2.xml b/src/test/resources/net_import_2.xml index 520d3c44045..4614a828a67 100644 --- a/src/test/resources/net_import_2.xml +++ b/src/test/resources/net_import_2.xml @@ -1,36 +1,33 @@ - - + new_model 1.0.0 - NEW New Model2 home2 - true - false - - + false + false + + NEW + newRole_3 newRole_3 - - - newVariable_7 - newVariable_7 - newVariable_6 newVariable_6 - - + + newVariable_7 + newVariable_7 + - 3 + t3 481 186 - + task3 + + t3_flex + - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/org_group.xml b/src/test/resources/org_group.xml deleted file mode 100644 index 0bbc98fe2af..00000000000 --- a/src/test/resources/org_group.xml +++ /dev/null @@ -1,492 +0,0 @@ - - - org_group - 1.0.0 - GRP - Organization group - home - true - false - - - - - group_id - Group ID - Enter group ID - ID of organization group - - id: f.group_id; - change id value { useCase.stringId } - - - - author - Group Author - - - group_name - Group name - Enter group name - Name of organization group - - name: f.group_name; - useCase.setTitle(name.value) - workflowService.save(useCase) - - - - user_selection - Select user - No user selected - Select user to be added as a group member - - userField: f.user_selection; - change userField value { null } - - - selection: f.members, - userField: f.user_selection; - change selection options { nextGroupService.addUser(userField.value, selection.options) } - - - - members - Members - Members of current organization group - - - - - - - user_action_selection - Select action - - - - - Add existing user - - action_selection: f.user_action_selection, - user_selection: f.user_selection, - invite_by_mail: f.invite_by_mail, - trans: t.8; - - make user_selection, editable on trans when { action_selection.value == "add" } - make invite_by_mail, hidden on trans when { action_selection.value == "add" } - - make user_selection, hidden on trans when { action_selection.value == "invite" } - make invite_by_mail, editable on trans when { action_selection.value == "invite" } - - - - invite_by_mail - Add e-mail address - example@example.com - Add e-meail address to send invitation - email - - - - Autor grupy - ID grupy - ID organizačnej grupy - Zadajte ID grupy - Názov grupy - Názov organizačnej grupy - Zadajte názov grupy - Vyberte nového používateľa - Vyberte nového používateľa pre pridanie do grupy - Nebol vybraný žiadny používateľ - Členovia grupy - Členovia organizačnej grupy - Vyberte akciu - Pridať existujúceho používateľa - Pozvať nového používateľa - Zadaj e-mail adresu - Zadaj e-mail adresu - - - - 2 - 420 - 220 - - - 0 - - auto - - group_id - - visible - - - 0 - 0 - 1 - 4 - 6 - - outline - - - - author - - visible - - - 0 - 1 - 1 - 4 - 6 - - outline - - - - group_name - - editable - - - 0 - 2 - 1 - 4 - 6 - - outline - - - - - 6 - 740 - 100 - - - 0 - - auto - - group_id - - visible - - - 0 - 0 - 1 - 4 - 0 - - outline - - - - author - - visible - - - 0 - 1 - 1 - 4 - 0 - - outline - - - - group_name - - visible - - - 0 - 2 - 1 - 4 - 0 - - outline - - - - members - - visible - - - 0 - 3 - 1 - 4 - 0 - - outline - - - - - 8 - 500 - 340 - - - 0 - - auto - - user_action_selection - - editable - - - 0 - 0 - 2 - 4 - 6 - - outline - - - - user_selection - - editable - - - 0 - 2 - 1 - 4 - 6 - - outline - - - - invite_by_mail - - hidden - - - 0 - 3 - 1 - 4 - 6 - - outline - - - - members - - visible - - - 0 - 4 - 1 - 4 - 6 - - outline - - - - invite_new_user - - - action_selection: f.user_action_selection, - invite_by_mail: f.invite_by_mail, - members: f.members; - - if(action_selection.value == "invite" && invite_by_mail.value != null){ - change members options { nextGroupService.inviteUser(invite_by_mail.value, members.options, useCase) - } - } - - - - - - 25 - 740 - 340 - - - 0 - - auto - - group_id - - visible - - - 0 - 0 - 1 - 4 - 6 - - outline - - - - author - - visible - - - 0 - 1 - 1 - 4 - 6 - - outline - - - - group_name - - editable - - - 0 - 2 - 1 - 4 - 6 - - outline - - - - - 28 - 500 - 100 - - - 0 - - auto - - members - - editable - - - 0 - 0 - 1 - 4 - 6 - - outline - - - - remove_user - - - members: f.members; - change members options { nextGroupService.removeUser(members.value, members.options, useCase) } - change members value { [] } - - - - - - - 1 - 220 - 220 - - 1 - false - - - 4 - 620 - 220 - - 0 - false - - - - 3 - regular - 1 - 2 - 1 - - - 5 - regular - 2 - 4 - 1 - - - 18 - read - 4 - 6 - 1 - - - 21 - regular - 4 - 8 - 1 - - - 22 - regular - 8 - 4 - 1 - - - 26 - regular - 4 - 25 - 1 - - - 27 - regular - 25 - 4 - 1 - - - 29 - regular - 28 - 4 - 1 - - - 30 - regular - 4 - 28 - 1 - - \ No newline at end of file diff --git a/src/test/resources/petriNet_import_failure.xml b/src/test/resources/petriNet_import_failure.xml new file mode 100644 index 00000000000..55bf07a4d78 --- /dev/null +++ b/src/test/resources/petriNet_import_failure.xml @@ -0,0 +1,31 @@ + + petriNet_import_failure + 1.0.0 + Test + false + false + + TST + + + + x123 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/petriNets/NAE-1616_duplicate_action_id.xml b/src/test/resources/petriNets/NAE-1616_duplicate_action_id.xml index e8bf6688c6f..38ea7303de6 100644 --- a/src/test/resources/petriNets/NAE-1616_duplicate_action_id.xml +++ b/src/test/resources/petriNets/NAE-1616_duplicate_action_id.xml @@ -1,19 +1,26 @@ - + NAE_1616 - NAE + 1.0.0 NAE-1616 - Cannot upload process with action id bug_report true true - false + + NAE + new_model_upload - println "process_upload_pre" + - println "process_upload_post" + @@ -21,69 +28,93 @@ new_model_create - println "case_create_pre" + - println "case_create_post" + new_model_delete - println "case_delete_pre" + - println "case_delete_post" + newRole_1 - <event type="cancel"> + <event type="remove"> <id>newRole_1_cancel</id> <actions phase="pre"> - <action id="7">println "role_cancel_pre"</action> + <action id="7"><![CDATA[ + println "role_cancel_pre" + ]]></action> </actions> <actions phase="post"> - <action id="8">println "role_cancel_post"</action> + <action id="8"><![CDATA[ + println "role_cancel_post" + ]]></action> </actions> </event> <event type="assign"> <id>newRole_1_assign</id> <actions phase="pre"> - <action id="9">println "role_assign_pre"</action> + <action id="9"><![CDATA[ + println "role_assign_pre" + ]]></action> </actions> <actions phase="post"> - <action id="10">println "role_assign_post"</action> + <action id="10"><![CDATA[ + println "role_assign_post" + ]]></action> </actions> </event> </role> <data type="text"> <id>text_0</id> <title/> - <action trigger="set" id="11"> - println "data_trigger_set" - </action> - <action trigger="get" id="12"> - println "data_trigger_get" - </action> <event type="set"> <id>text_0_set</id> <actions phase="pre"> - <action id="13">println "data_set_pre"</action> + <action id="13"><![CDATA[ + println "data_set_pre" + ]]></action> </actions> <actions phase="post"> - <action id="14">println "data_set_post"</action> + <action id="14"><![CDATA[ + println "data_set_post" + ]]></action> + <action id="11"><![CDATA[ + println "data_trigger_set" + ]]></action> </actions> </event> <event type="get"> <id>text_0_get</id> <actions phase="pre"> - <action id="15">println "data_get_pre"</action> + <action id="15"><![CDATA[ + println "data_get_pre" + ]]></action> + <action id="12"><![CDATA[ + println "data_trigger_get" + ]]></action> </actions> <actions phase="post"> - <action id="16">println "data_get_post"</action> + <action id="16"><![CDATA[ + println "data_get_post" + ]]></action> </actions> </event> </data> @@ -95,114 +126,147 @@ <id>t1</id> <x>420</x> <y>140</y> - <label/> - <dataRef> - <id>text_1</id> - <logic> - <action trigger="get" id="31"> - println "text_1_dataref_trigger_get" - </action> - <action trigger="set" id="32"> - println "text_1_dataref_trigger_set" - </action> - </logic> - <event type="set"> - <id>text_1_set</id> - <actions phase="pre"> - <action id="33">println "text_1_dataref_set_pre"</action> - </actions> - <actions phase="post"> - <action id="34">println "text_1_dataref_set_post"</action> - </actions> - </event> - <event type="get"> - <id>text_1_get</id> - <actions phase="pre"> - <action id="35">println "text_1_dataref_get_pre"</action> - </actions> - <actions phase="post"> - <action id="36">println "text_1_dataref_get_post"</action> - </actions> - </event> - </dataRef> - <dataGroup> - <id>t1_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>text_0</id> - <logic> - <behavior>editable</behavior> - <action trigger="get" id="17"> - println "text_0_dataref_trigger_get" - </action> - <action trigger="set" id="18"> - println "text_0_dataref_trigger_set" - </action> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - <event type="set"> - <id>text_0_set</id> - <actions phase="pre"> - <action id="19">println "text_0_dataref_set_pre"</action> - </actions> - <actions phase="post"> - <action id="20">println "text_0_dataref_set_post"</action> - </actions> - </event> - <event type="get"> - <id>text_0_get</id> - <actions phase="pre"> - <action id="21">println "text_0_dataref_get_pre"</action> - </actions> - <actions phase="post"> - <action id="22">println "text_0_dataref_get_post"</action> - </actions> - </event> - </dataRef> - </dataGroup> + <title/> + <flex> + <id>t1_flex</id> + <item> + <dataRef> + <id>text_0</id> + <logic> + <behavior>editable</behavior> + </logic> + <event type="set"> + <id>text_0_set</id> + <actions phase="pre"> + <action id="19"><![CDATA[ + println "text_0_dataref_set_pre" + ]]></action> + </actions> + <actions phase="post"> + <action id="20"><![CDATA[ + println "text_0_dataref_set_post" + ]]></action> + <action id="18"><![CDATA[ + println "text_0_dataref_trigger_set" + ]]></action> + </actions> + </event> + <event type="get"> + <id>text_0_get</id> + <actions phase="pre"> + <action id="21"><![CDATA[ + println "text_0_dataref_get_pre" + ]]></action> + <action id="17"><![CDATA[ + println "text_0_dataref_trigger_get" + ]]></action> + </actions> + <actions phase="post"> + <action id="22"><![CDATA[ + println "text_0_dataref_get_post" + ]]></action> + </actions> + </event> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>text_1</id> + <logic> + <behavior>editable</behavior> + </logic> + <event type="set"> + <id>text_1_set</id> + <actions phase="pre"> + <action id="33">println "text_1_dataref_set_pre"</action> + </actions> + <actions phase="post"> + <action id="34">println "text_1_dataref_set_post"</action> + <action id="32"> + println "text_1_dataref_trigger_set" + </action> + </actions> + </event> + <event type="get"> + <id>text_1_get</id> + <actions phase="pre"> + <action id="35">println "text_1_dataref_get_pre"</action> + <action id="31"> + println "text_1_dataref_trigger_get" + </action> + </actions> + <actions phase="post"> + <action id="36">println "text_1_dataref_get_post"</action> + </actions> + </event> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + </flex> <event type="assign"> <id>t1_assign</id> <actions phase="pre"> - <action id="23">println "task_assign_pre"</action> + <action id="23"><![CDATA[ + println "task_assign_pre" + ]]></action> </actions> <actions phase="post"> - <action id="24">println "task_assign_post"</action> + <action id="24"><![CDATA[ + println "task_assign_post" + ]]></action> </actions> </event> <event type="cancel"> <id>t1_cancel</id> <actions phase="pre"> - <action id="25">println "task_cancel_pre"</action> + <action id="25"><![CDATA[ + println "task_cancel_pre" + ]]></action> </actions> <actions phase="post"> - <action id="26">println "task_cancel_post"</action> + <action id="26"><![CDATA[ + println "task_cancel_post" + ]]></action> </actions> </event> - <event type="delegate"> + <event type="reassign"> <id>t1_delegate</id> <actions phase="pre"> - <action id="27">println "task_delegate_pre"</action> + <action id="27"><![CDATA[ + println "task_delegate_pre" + ]]></action> </actions> <actions phase="post"> - <action id="28">println "task_delegate_post"</action> + <action id="28"><![CDATA[ + println "task_delegate_post" + ]]></action> </actions> </event> <event type="finish"> <id>t1_finish</id> <actions phase="pre"> - <action id="29">println "task_finish_pre"</action> + <action id="29"> + <![CDATA[ + println "task_finish_pre" + ]]> + </action> </actions> <actions phase="post"> - <action id="30">println "task_finish_post"</action> + <action id="30"> + <![CDATA[ + println "task_finish_post" + ]]> + </action> </actions> </event> </transition> -</document> \ No newline at end of file +</process> \ No newline at end of file diff --git a/src/test/resources/petriNets/NAE-1858_allDataTask.xml b/src/test/resources/petriNets/NAE-1858_allDataTask.xml index 8dd6e9cf9fb..9d7a3414fbd 100644 --- a/src/test/resources/petriNets/NAE-1858_allDataTask.xml +++ b/src/test/resources/petriNets/NAE-1858_allDataTask.xml @@ -1,35 +1,15 @@ -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> - <id>NAE-1858</id> - <initials>NAE</initials> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> + <id>NAE_1858</id> + <version>1.0.0</version> <title>NAE-1858 - Task states device_hub true true - false - - text_0 - - </data> - <data type="number"> - <id>number_0</id> - <title/> - </data> - <data type="enumeration"> - <id>enumeration_0</id> - <title/> - </data> - <data type="enumeration_map"> - <id>enumeration_map_0</id> - <title/> - </data> - <data type="multichoice"> - <id>multichoice_0</id> - <title/> - </data> - <data type="multichoice_map"> - <id>multichoice_map_0</id> - <title/> - </data> + <properties> + <property key="initials">NAE</property> + </properties> + <processEvents/> + <caseEvents/> <data type="boolean"> <id>boolean_0</id> <title/> @@ -42,27 +22,27 @@ <data type="date"> <id>date_0</id> <title/> - <init>2023-03-20T09:01:18.813Z</init> + <init>2023-03-20</init> </data> <data type="dateTime"> <id>dateTime_0</id> <title/> <init>2023-03-20T09:01:20.484Z</init> </data> - <data type="file"> - <id>file_0</id> + <data type="enumeration"> + <id>enumeration_0</id> <title/> </data> - <data type="fileList"> - <id>fileList_0</id> + <data type="enumeration_map"> + <id>enumeration_map_0</id> <title/> </data> - <data type="user"> - <id>user_0</id> + <data type="file"> + <id>file_0</id> <title/> </data> - <data type="userList"> - <id>userList_0</id> + <data type="fileList"> + <id>fileList_0</id> <title/> </data> <data type="filter"> @@ -73,313 +53,291 @@ <id>i18n_0</id> <title/> </data> + <data type="multichoice"> + <id>multichoice_0</id> + <title/> + </data> + <data type="multichoice_map"> + <id>multichoice_map_0</id> + <title/> + </data> + <data type="number"> + <id>number_0</id> + <title/> + </data> <data type="taskRef"> <id>taskRef_0</id> <title/> </data> + <data type="text"> + <id>text_0</id> + <title/> + </data> <data type="text"> <id>text_1</id> <title/> <component> - <name>htmltextarea</name> + <id>htmltextarea</id> </component> </data> + <data type="user"> + <id>user_0</id> + <title/> + </data> + <data type="userList"> + <id>userList_0</id> + <title/> + </data> <transition> <id>t1</id> <x>340</x> <y>100</y> - <label>simple</label> - <dataGroup> - <id>t1_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>text_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>number_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>0</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>enumeration_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>enumeration_map_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>1</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>multichoice_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>2</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>multichoice_map_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>2</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>boolean_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>3</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>button_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>3</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>date_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>4</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>dateTime_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>4</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>file_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>5</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>fileList_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>5</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>user_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>6</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>userList_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>6</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>filter_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>7</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>i18n_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>7</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>taskRef_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>8</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="assign"> - <id>t1_assign</id> - </event> - <event type="finish"> - <id>t1_finish</id> - </event> - <event type="cancel"> - <id>t1_cancel</id> - </event> - <event type="delegate"> - <id>t1_delegate</id> - </event> + <title>simple + + t1_flex + + + text_0 + + editable + + + + 0 + 0 + 1 + + + + + number_0 + + editable + + + + 0 + 0 + 1 + + + + + enumeration_0 + + editable + + + + 0 + 0 + 1 + + + + + enumeration_map_0 + + editable + + + + 0 + 0 + 1 + + + + + multichoice_0 + + editable + + + + 0 + 0 + 1 + + + + + multichoice_map_0 + + editable + + + + 0 + 0 + 1 + + + + + boolean_0 + + editable + + + + 0 + 0 + 1 + + + + + button_0 + + editable + + + + 0 + 0 + 1 + + + + + date_0 + + editable + + + + 0 + 0 + 1 + + + + + dateTime_0 + + editable + + + + 0 + 0 + 1 + + + + + file_0 + + editable + + + + 0 + 0 + 1 + + + + + fileList_0 + + editable + + + + 0 + 0 + 1 + + + + + user_0 + + editable + + + + 0 + 0 + 1 + + + + + userList_0 + + editable + + + + 0 + 0 + 1 + + + + + filter_0 + + editable + + + + 0 + 0 + 1 + + + + + i18n_0 + + editable + + + + 0 + 0 + 1 + + + + + taskRef_0 + + editable + + + + 0 + 0 + 1 + + + t2 580 100 - - - t2_0 - 4 - grid - - text_1 - - editable - - - 0 - 0 - 2 - 4 - - outline - - - - - t2_assign - - - t2_finish - - - t2_cancel - - - t2_delegate - + component + + t2_flex + + + text_1 + + editable + + + + 0 + 0 + 1 + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/NAE-1858_task_state.xml b/src/test/resources/petriNets/NAE-1858_task_state.xml index 7b5871c0559..8642fa165df 100644 --- a/src/test/resources/petriNets/NAE-1858_task_state.xml +++ b/src/test/resources/petriNets/NAE-1858_task_state.xml @@ -1,11 +1,14 @@ - + new_model - NEW + 1.0.0 New Model device_hub true true - false + + NEW + newVariable_1 @@ -15,269 +18,247 @@ <id>t1</id> <x>540</x> <y>140</y> - <!--TODO:NAE-1858 - this task should be disabled--> - <label>N-</label> - </transition> - <transition> - <id>t2</id> - <x>540</x> - <y>220</y> - <label>N</label> - </transition> - <transition> - <id>t3</id> - <x>540</x> - <y>300</y> - <label>Y</label> - </transition> - <transition> - <id>t4</id> - <x>540</x> - <y>380</y> - <label>Y</label> - </transition> - <transition> - <id>t5</id> - <x>540</x> - <y>460</y> - <label>N</label> - </transition> - <transition> - <id>t6</id> - <x>540</x> - <y>540</y> - <label>Y</label> - </transition> - <transition> - <id>t7</id> - <x>900</x> - <y>540</y> - <label>N</label> - </transition> - <transition> - <id>t8</id> - <x>900</x> - <y>460</y> - <label>Y</label> - </transition> - <transition> - <id>t9</id> - <x>900</x> - <y>380</y> - <label>N</label> + <title>N t10 900 300 - + Y t11 900 220 - + N t12 900 140 - + Y t13 1260 140 - + Y t14 1260 220 - + Y t15 1260 300 - + N t16 1260 380 - + Y t17 1260 460 - + N t18 1260 540 - + Y t19 540 620 - + Y + + + t2 + 540 + 220 + N t20 540 700 - + N - - p1 - 380 - 140 - 1 - false - - - p2 - 380 - 220 - 0 - false - - - p3 - 380 + + t3 + 540 300 - 3 - false - - - p4 - 380 + Y + + + t4 + 540 380 - 3 - false - - - p5 - 380 + Y + + + t5 + 540 460 - 1 - false - - - p6 - 380 + N + + + t6 + 540 540 - 0 - false - + Y + + + t7 + 900 + 540 + N + + + t8 + 900 + 460 + Y + + + t9 + 900 + 380 + N + - p8 - 740 - 220 + p1 + 380 + 140 1 - false - - - p9 - 740 - 300 - 0 - false p10 740 380 5 - false p11 740 460 2 - false p12 740 540 3 - false p13 300 380 1 - false p14 300 460 3 - false p15 1100 140 4 - false p16 1100 220 1 - false p17 1100 300 0 - false p18 1100 380 5 - false p19 1100 460 2 - false + + + p2 + 380 + 220 + 0 p20 1100 540 3 - false p21 380 620 5 - false p22 380 700 2 - false + + + p3 + 380 + 300 + 3 + + + p4 + 380 + 380 + 3 + + + p5 + 380 + 460 + 1 + + + p6 + 380 + 540 + 0 + + + p8 + 740 + 220 + 1 + + + p9 + 740 + 300 + 0 a1 @@ -286,68 +267,6 @@ t1 1 - - a2 - regular - p1 - t1 - 1 - - 460 - 100 - - - - a3 - regular - p2 - t2 - 1 - - - a4 - regular - p3 - t3 - 1 - - - a5 - regular - p4 - t4 - 1 - p13 - - - a6 - regular - p5 - t5 - 3 - p14 - - - a7 - reset - p6 - t6 - 1 - - - a8 - inhibitor - p8 - t11 - 1 - - - a9 - inhibitor - p9 - t10 - 1 - a10 inhibitor @@ -411,20 +330,94 @@ t13 1 + + a2 + regular + p1 + t1 + 1 + + 460 + 100 + + a20 regular p21 t19 - 3 - newVariable_1 + + + a21 regular p22 t20 - 3 - newVariable_1 + + + + + + a3 + regular + p2 + t2 + 1 + + + a4 + regular + p3 + t3 + 1 + + + a5 + regular + p4 + t4 + + + + + + a6 + regular + p5 + t5 + + + + + + a7 + reset + p6 + t6 + 1 + + + a8 + inhibitor + p8 + t11 + 1 + + + a9 + inhibitor + p9 + t10 + 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/NAE-1858_task_state_2.xml b/src/test/resources/petriNets/NAE-1858_task_state_2.xml index 23e03417776..25afd08c125 100644 --- a/src/test/resources/petriNets/NAE-1858_task_state_2.xml +++ b/src/test/resources/petriNets/NAE-1858_task_state_2.xml @@ -1,63 +1,61 @@ - + new_model 1.0.0 - NEW New Model home true true - false + + NEW + t1 460 100 - t2 580 355 - - 0 - - + Manual p1 171 343 - 1 - false p2 438 339 - 0 - false p3 710 343 - 0 - false @@ -85,4 +73,4 @@ p3 1 - + diff --git a/src/test/resources/petriNets/NAE_1382_first_trans_auto_2.xml b/src/test/resources/petriNets/NAE_1382_first_trans_auto_2.xml index 31cd5b9ba1d..3cda5f81cff 100644 --- a/src/test/resources/petriNets/NAE_1382_first_trans_auto_2.xml +++ b/src/test/resources/petriNets/NAE_1382_first_trans_auto_2.xml @@ -1,10 +1,9 @@ - + NAE_1382_first_trans_auto - ERR + 1.0.0 New Model true - false @@ -16,10 +15,7 @@ t5 740 140 - - 0 - - + auto @@ -27,10 +23,7 @@ t4 420 140 - - 0 - - + auto @@ -38,78 +31,57 @@ first 140 500 - - 0 - - + Manual t1 300 260 - - 0 - - + Auto t2 580 340 - - 0 - - + Manuel p9 580 220 - 0 - false p8 580 100 - 0 - false p1 180 340 - 0 - false p3 700 340 - 0 - false p4 60 500 - 1 - false p7 420 260 - 0 - false @@ -182,4 +154,4 @@ p7 1 - + diff --git a/src/test/resources/petriNets/action_delegate_concurrency_test.xml b/src/test/resources/petriNets/action_delegate_concurrency_test.xml index 4523fe8d791..6e50f406692 100644 --- a/src/test/resources/petriNets/action_delegate_concurrency_test.xml +++ b/src/test/resources/petriNets/action_delegate_concurrency_test.xml @@ -1,39 +1,37 @@ - - + action_delegate_concurrency_test 1.0.0 - TRE Tree Node nature true - false - - - + false + + TRE + + + text title - - 1 + t1 546 177 - + task - 1 + t1 - - text: f.text; + + + ]]> + - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/all_data_refs.xml b/src/test/resources/petriNets/all_data_refs.xml index 69eb782f3b3..1bb5be726c0 100644 --- a/src/test/resources/petriNets/all_data_refs.xml +++ b/src/test/resources/petriNets/all_data_refs.xml @@ -1,556 +1,635 @@ - - - all_data - All Data - ALL - + + all_data + 1.0.0 + All Data + false + false + + ALL + + + process_role Process role - - - number - Number - 10000 + + boolean + Boolean - - number_currency - Number currency - 10000 - - - EUR - 2 - sk_SK - - + + button + Button + Push - - - text - Text - Lorem ipsum + + date + Date - - text_area - Text area - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vitae magna in libero semper - vulputate ut eu sapien. Phasellus vel. - + + datetime + Datetime - enumeration Enumeration - Alice - Bob - Carol + + + + + Bob enumeration_autocomplete Enumeration autocomplete - Alice - Bob - Carol + + + + + Bob - - - + + autocomplete + enumeration_list Enumeration list - Alice - Bob - Carol + + + + + Bob - - - + + list + + + + file + File + + file_set + + + + + + + + + fileList + File list - multichoice Multichoice - Alice - Bob - Carol + + + + + Alice,Bob multichoice_list Multichoice list - Alice - Bob - Carol + + + + + Alice,Bob - - - + + list + - - - boolean - Boolean + + number + Number + 10000 - - - date - Date + + number_currency + Number currency + 10000 + + currency + + sk_SK + EUR + 2 + + - - - file - File - - - textfield: f.text; - change textfield value { - "funguje to" - } - - + + text + Text + Lorem ipsum - - - fileList - File list + + text_area + Text area + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vitae magna in libero semper + vulputate ut eu sapien. Phasellus vel. - user User - - - datetime - Datetime - - - - button - Button - Push - - - 1 + t1 379 273 - 6 - + Task - editable auto process_role - + true - + - - number - Number fields - false - 2 - - number - - editable - - - - number_currency - - editable - - - - - text - Text fields - false - - text - - editable - - - - text_area - - editable - - - - - enumeration - Enumeration fields - false - - enumeration - - editable - - - - enumeration_autocomplete - - editable - - - - enumeration_list - - editable - - - - - multichoice - Multichoice fields - false - - multichoice - - editable - - - - multichoice_list - - editable - - - - - boolean - Boolean fields - false - - boolean - - editable - - - - - date - Date fields - false - - date - - editable - - - - datetime - - editable - - - - - file - File fields - false - - file - - editable - - - - - fileList - File list fields - false - - fileList - - editable - - - - - user - User fields - false - - user - - editable - - - - - button - Button fields - false - - button - - editable - - - + + t1_flex + + + number + + editable + + + + 0 + 0 + 1 + + + + + number_currency + + editable + + + + 0 + 0 + 1 + + + + + text + + editable + + + + 0 + 0 + 1 + + + + + text_area + + editable + + + + 0 + 0 + 1 + + + + + enumeration + + editable + + + + 0 + 0 + 1 + + + + + enumeration_autocomplete + + editable + + + + 0 + 0 + 1 + + + + + enumeration_list + + editable + + + + 0 + 0 + 1 + + + + + multichoice + + editable + + + + 0 + 0 + 1 + + + + + multichoice_list + + editable + + + + 0 + 0 + 1 + + + + + boolean + + editable + + + + 0 + 0 + 1 + + + + + date + + editable + + + + 0 + 0 + 1 + + + + + datetime + + editable + + + + 0 + 0 + 1 + + + + + file + + editable + + + + 0 + 0 + 1 + + + + + fileList + + editable + + + + 0 + 0 + 1 + + + + + user + + editable + + + + 0 + 0 + 1 + + + + + button + + editable + + + + 0 + 0 + 1 + + + - 2 + t2 379 273 - + Task - visible auto process_role - + true - + - - number - Number fields - false - - number - - visible - - - - number_currency - - visible - - - - - text - Text fields - false - - text - - visible - - - - text_area - - visible - - - - - enumeration - Enumeration fields - false - - enumeration - - visible - - - - enumeration_autocomplete - - visible - - - - enumeration_list - - visible - - - - - multichoice - Multichoice fields - false - - multichoice - - visible - - - - multichoice_list - - visible - - - - - boolean - Boolean fields - false - - boolean - - visible - - - - - date - Date fields - false - - date - - visible - - - - datetime - - visible - - - - - file - File fields - false - - file - - visible - - - - - user - User fields - false - - user - - visible - - - - - button - Button fields - false - - button - - visible - - - + + t2_flex + + + number + + visible + + + + 0 + 0 + 1 + + + + + number_currency + + visible + + + + 0 + 0 + 1 + + + + + text + + visible + + + + 0 + 0 + 1 + + + + + text_area + + visible + + + + 0 + 0 + 1 + + + + + enumeration + + visible + + + + 0 + 0 + 1 + + + + + enumeration_autocomplete + + visible + + + + 0 + 0 + 1 + + + + + enumeration_list + + visible + + + + 0 + 0 + 1 + + + + + multichoice + + visible + + + + 0 + 0 + 1 + + + + + multichoice_list + + visible + + + + 0 + 0 + 1 + + + + + boolean + + visible + + + + 0 + 0 + 1 + + + + + date + + visible + + + + 0 + 0 + 1 + + + + + datetime + + visible + + + + 0 + 0 + 1 + + + + + file + + visible + + + + 0 + 0 + 1 + + + + + user + + visible + + + + 0 + 0 + 1 + + + + + button + + visible + + + + 0 + 0 + 1 + + + - 3 + t3 379 273 - + Datagroups auto process_role - + true - + - - stretch - Stretch - start - true - - text - - visible - - - - number - - editable - - - - enumeration - - editable - - - - - right - Alignment - Right - end - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - - - left - Alignment - Left - start - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - - - center - Alignment - Center - center - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - + + t3_flex + + + text + + visible + + + + 0 + 0 + 1 + + + + + number + + editable + + + + 0 + 0 + 1 + + + + + enumeration + + visible + + + + 0 + 0 + 1 + + + - + \ No newline at end of file diff --git a/src/test/resources/petriNets/async.xml b/src/test/resources/petriNets/async.xml index c8d0a610bbc..63439b9f3e4 100644 --- a/src/test/resources/petriNets/async.xml +++ b/src/test/resources/petriNets/async.xml @@ -1,11 +1,13 @@ - - new_model - NEW - New Model - device_hub - true - true - false + + new_model + 1.0.0 + New Model + device_hub + true + true + + NEW + text_0 @@ -18,51 +20,45 @@ <id>text_2</id> <title/> </data> - <transition> - <id>t1</id> - <x>340</x> - <y>140</y> - <label/> - <dataGroup> - <id>t1_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>text_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>text_1</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="finish"> - <id>t1_finish</id> - <actions phase="pre"> - <action id="1"> - <!--@formatter:off--> - field0: f.text_0, - field1: f.text_1; + <transition> + <id>t1</id> + <x>340</x> + <y>140</y> + <title/> + <flex> + <id>t1_flex</id> + <item> + <dataRef> + <id>text_0</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>text_1</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + </flex> + <event type="finish"> + <id>t1_finish</id> + <actions phase="pre"> + <action id="1"> + <![CDATA[ setData(new DataSet([ "text_0": new TextField(rawValue: "A") ])) @@ -71,140 +67,132 @@ setData(new DataSet([ "text_1": new TextField(rawValue: "B") ])) - <!--@formatter:on--> + ]]> </action> - </actions> - </event> - </transition> - <transition> - <id>t2</id> - <x>660</x> - <y>140</y> - <label/> - <dataGroup> - <id>t2_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>text_1</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>text_2</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> + </actions> + </event> + </transition> + <transition> + <id>t2</id> + <x>660</x> + <y>140</y> + <title/> + <flex> + <id>t2_flex</id> + <item> + <dataRef> + <id>text_1</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>text_2</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + </flex> <event type="assign"> <id>t2_assign</id> <actions phase="pre"> - <action> - field1: f.text_1, - field2: f.text_2; + <action id="action_0"> + <![CDATA[ setData(new DataSet([ "text_1": new TextField(rawValue: "D"), "text_2": new TextField(rawValue: "E") ])) + ]]> </action> </actions> </event> <event type="finish"> <id>t2_finish</id> <actions phase="pre"> - <action> - field1: f.text_1, - field2: f.text_2; + <action id="action_1"> + <![CDATA[ setData(new DataSet([ "text_1": new TextField(rawValue: "G"), "text_2": new TextField(rawValue: "H") ])) + ]]> </action> </actions> <actions phase="post"> - <action> - field1: f.text_1, - field2: f.text_2; + <action id="action_2"> + <![CDATA[ setData(new DataSet([ "text_1": new TextField(rawValue: "J"), "text_2": new TextField(rawValue: "K") ])) + ]]> </action> </actions> </event> - </transition> - <place> - <id>p1</id> - <x>580</x> - <y>140</y> - <tokens>1</tokens> - <static>false</static> - </place> - <place> - <id>p2</id> - <x>740</x> - <y>140</y> - <tokens>0</tokens> - <static>false</static> - </place> - <place> - <id>p3</id> - <x>260</x> - <y>140</y> - <tokens>1</tokens> - <static>false</static> - </place> - <place> - <id>p4</id> - <x>420</x> - <y>140</y> - <tokens>0</tokens> - <static>false</static> - </place> - <arc> - <id>a1</id> - <type>regular</type> - <sourceId>p1</sourceId> - <destinationId>t2</destinationId> - <multiplicity>1</multiplicity> - </arc> - <arc> - <id>a2</id> - <type>regular</type> - <sourceId>t2</sourceId> - <destinationId>p2</destinationId> - <multiplicity>1</multiplicity> - </arc> - <arc> - <id>a3</id> - <type>regular</type> - <sourceId>p3</sourceId> - <destinationId>t1</destinationId> - <multiplicity>1</multiplicity> - </arc> - <arc> - <id>a4</id> - <type>regular</type> - <sourceId>t1</sourceId> - <destinationId>p4</destinationId> - <multiplicity>1</multiplicity> - </arc> -</document> \ No newline at end of file + </transition> + <place> + <id>p1</id> + <x>580</x> + <y>140</y> + <tokens>1</tokens> + </place> + <place> + <id>p2</id> + <x>740</x> + <y>140</y> + <tokens>0</tokens> + </place> + <place> + <id>p3</id> + <x>260</x> + <y>140</y> + <tokens>1</tokens> + </place> + <place> + <id>p4</id> + <x>420</x> + <y>140</y> + <tokens>0</tokens> + </place> + <arc> + <id>a1</id> + <type>regular</type> + <sourceId>p1</sourceId> + <destinationId>t2</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <id>a2</id> + <type>regular</type> + <sourceId>t2</sourceId> + <destinationId>p2</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <id>a3</id> + <type>regular</type> + <sourceId>p3</sourceId> + <destinationId>t1</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <id>a4</id> + <type>regular</type> + <sourceId>t1</sourceId> + <destinationId>p4</destinationId> + <multiplicity>1</multiplicity> + </arc> +</process> \ No newline at end of file diff --git a/src/test/resources/petriNets/case_authorization_default_test.xml b/src/test/resources/petriNets/case_authorization_default_test.xml new file mode 100644 index 00000000000..4a6cd53ba66 --- /dev/null +++ b/src/test/resources/petriNets/case_authorization_default_test.xml @@ -0,0 +1,18 @@ +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> + <id>case_authorization_default_test</id> + <version>1.0.0</version> + <title>Case authorization test + true + false + + CAT + + + default + + true + true + true + + + \ No newline at end of file diff --git a/src/test/resources/petriNets/case_authorization_test.xml b/src/test/resources/petriNets/case_authorization_test.xml new file mode 100644 index 00000000000..8fd8816e80e --- /dev/null +++ b/src/test/resources/petriNets/case_authorization_test.xml @@ -0,0 +1,58 @@ + + case_authorization_test + 1.0.0 + Case authorization test + false + false + + CAT + + + neg_process_role + + false + false + false + + + + pos_process_role + + true + true + true + + + + neg_case_role + + false + false + false + + + + pos_case_role + + true + true + true + + + + neg_process_role + neg process role + + + pos_process_role + pos create role + + + neg_case_role + + </data> + <data type="userList"> + <id>pos_case_role</id> + <title/> + </data> +</process> \ No newline at end of file diff --git a/src/test/resources/petriNets/change_field_value_init.xml b/src/test/resources/petriNets/change_field_value_init.xml index e7c15c4582a..4841f9e8b2a 100644 --- a/src/test/resources/petriNets/change_field_value_init.xml +++ b/src/test/resources/petriNets/change_field_value_init.xml @@ -1,124 +1,165 @@ -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>change_field_value_init</id> + <version>1.0.0</version> <title>change_field_value_init true - CFVI - - - text_static - text_static - TEST VALUE - - + false + + CFVI + + + text_dynamic text_dynamic - text_static.rawValue + " DYNAMIC" + - + + text_static + text_static + TEST VALUE + transition0 0 0 - - - - text_static - - editable - - - - text_dynamic - - editable - - - + whatever 0 + + transition0_flex + + + text_static + + editable + + + + 0 + 0 + 1 + + + + + text_dynamic + + editable + + + + 0 + 0 + 1 + + + finish - - - text_static: f.text_static, - text_dynamic: f.text_dynamic; - + + + ]]> + - transition1 0 0 - - - - text_static - - editable - - - - text_dynamic - - editable - - - + whatever 1 + + transition1_flex + + + text_static + + editable + + + + 0 + 0 + 1 + + + + + text_dynamic + + editable + + + + 0 + 0 + 1 + + + finish - - - text_static: f.text_static, - text_dynamic: f.text_dynamic; - + + + ]]> + - transition2 0 0 - - - - text_static - - editable - - - - text_dynamic - - editable - - - + whatever 2 + + transition2_flex + + + text_static + + editable + + + + 0 + 0 + 1 + + + + + text_dynamic + + editable + + + + 0 + 0 + 1 + + + finish - - - text_static: f.text_static, - text_dynamic: f.text_dynamic; - + + + ]]> + - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/changed_fields_allowed_nets.xml b/src/test/resources/petriNets/changed_fields_allowed_nets.xml index d88677a8a3a..dd22984d5e3 100644 --- a/src/test/resources/petriNets/changed_fields_allowed_nets.xml +++ b/src/test/resources/petriNets/changed_fields_allowed_nets.xml @@ -1,76 +1,64 @@ - - + changed_fields_allowed_nets - NEW + 1.0.0 New Model true - false - - - - - - - text - - caseRef: f.caseRef, - caseRef2: f.caseRef2; - - change caseRef allowedNets { - [useCase.processIdentifier] - } - - change caseRef2 allowedNets { - caseRef2.getAllowedNets() + useCase.processIdentifier - } - - - caseRef: f.caseRef, - caseRef2: f.caseRef2; - - + false + + NEW + + + caseRef - + </data> <data type="caseRef"> <id>caseRef2</id> - <title> + <allowedNets> - <allowedNet>org_group</allowedNet> + <allowedNet>all_data</allowedNet> </allowedNets> </data> - <!-- I18NS --> - <!-- TRANSITIONS --> + <data type="text"> + <id>text</id> + <title/> + <event type="set"> + <id>text_set</id> + <actions phase="post"> + <action id="action_0"> + <![CDATA[ + change caseRef allowedNets { + [useCase.processIdentifier] + } + change caseRef2 allowedNets { + caseRef2.getAllowedNets() + useCase.processIdentifier + } + ]]> + </action> + </actions> + </event> + </data> <transition> <id>t1</id> <x>501</x> <y>247</y> - <layout> - <offset>0</offset> - </layout> - <label>Task</label> - <dataGroup> - <id>DataGroup_0</id> - <layout>grid</layout> - <dataRef> - <id>text</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>1</cols> - <offset>0</offset> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> + <title>Task + + t1_flex + + + text + + editable + + + + 0 + 0 + 1 + + + - - - + \ No newline at end of file diff --git a/src/test/resources/petriNets/dynamic_case_name_test.xml b/src/test/resources/petriNets/dynamic_case_name_test.xml index f18165cc808..e01101f14ef 100644 --- a/src/test/resources/petriNets/dynamic_case_name_test.xml +++ b/src/test/resources/petriNets/dynamic_case_name_test.xml @@ -1,33 +1,42 @@ - + dynamic_choices + 1.0.0 dynamic_choices true - DVT - - - new I18nString("SK $text.rawValue" as String, ["en": "EN $text.rawValue" as String]) - - + false + + DVT + + "SK text value ${1+2+3}" number number - 1 + 2 + 3 + + + text text - "text value ${number.rawValue as Integer}" as String + - + + "EN text value ${1+2+3}" + transition 200 200 - + Transition auto + + transition_flex + - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/dynamic_choices.xml b/src/test/resources/petriNets/dynamic_choices.xml index 89ffc46aedd..b650d65afb9 100644 --- a/src/test/resources/petriNets/dynamic_choices.xml +++ b/src/test/resources/petriNets/dynamic_choices.xml @@ -1,66 +1,94 @@ - + dynamic_choices + 1.0.0 dynamic_choices true - DVT - + false + + DVT + enumeration enumeration - ["A", "B", "C"] + + + enumeration_map enumeration_map - - ["a": "A", "b": "B"] - multichoice multichoice - ["A", "B", "C"] + + + multichoice_map multichoice_map - - ["a": "A", "b": "B"] - - transition 200 200 - + Transition auto - - - enumeration - - editable - - - - enumeration_map - - editable - - - - multichoice - - editable - - - - multichoice_map - - editable - - + + transition_flex + + + enumeration + + editable + + + + 0 + 0 + 1 + + + + + enumeration_map + + editable + + + + 0 + 0 + 1 + + + + + multichoice + + editable + + + + 0 + 0 + 1 + + + + + multichoice_map + + editable + + + + 0 + 0 + 1 + + + - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/dynamic_init.xml b/src/test/resources/petriNets/dynamic_init.xml index d7593bed06a..56b2603e744 100644 --- a/src/test/resources/petriNets/dynamic_init.xml +++ b/src/test/resources/petriNets/dynamic_init.xml @@ -1,54 +1,44 @@ - + dynamic_init + 1.0.0 dynamic_init true - DVT - - - text - Text - userService.findByEmail("super@netgrif.com", true).name - - - - number - number - userService.findByEmail("super@netgrif.com", true).name.length() - - + false + + DVT + date date - java.time.LocalDate.now() + + + - dateTime dateTime - java.time.LocalDateTime.now() - - - - user - user - def user = userService.getLoggedOrSystem() - return new com.netgrif.application.engine.petrinet.domain.dataset.UserFieldValue(user.getStringId(), user.name, user.surname, user.email) + - multichoice multichoice - ABC - DEF - GHI + + + + + - ["ABC", "DEF"] + - multichoice_map multichoice_map @@ -58,46 +48,113 @@ - ["ABC", "DEF"] + + + + + number + number + + + + + + text + Text + + + + + + user + User + + - transition 0 0 - - - - text - - editable - - - - number - - editable - - - - date - - editable - - - - dateTime - - editable - - - - user - - editable - - + whatever + + transition_flex + + + text + + editable + + + + 0 + 0 + 1 + + + + + number + + editable + + + + 0 + 0 + 1 + + + + + date + + editable + + + + 0 + 0 + 1 + + + + + dateTime + + editable + + + + 0 + 0 + 1 + + + + + user + + editable + + + + 0 + 0 + 1 + + + - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/dynamic_validations.xml b/src/test/resources/petriNets/dynamic_validations.xml deleted file mode 100644 index 892960bfa6c..00000000000 --- a/src/test/resources/petriNets/dynamic_validations.xml +++ /dev/null @@ -1,132 +0,0 @@ - - dynamic_validations - dynamic_validations - true - DVT - - - min - Min - - - max - Max - 5 - - - number - Number - - - inrange ${min.value as Integer},${max.value as Integer} - Number field validation message - - - - - text - Text - - - maxLength ${max.value as Integer} - Text field validation message - - - - - date - Date - - - between past,today-P${max.value as Integer}D - Date field validation message - - - - - - number_valid_switch - Switch - - - number_valid_switch: f.number_valid_switch, - number: f.number; - - if (number_valid_switch.value) { - change number validations { "odd" } - } else { - change number validations { dynamicValidation('''inrange ${min.value as Integer},${max.value as Integer}''', - null) } - } - - - - - text_valid_switch - Switch - - - text_valid_switch: f.text_valid_switch, - text: f.text; - - if (text_valid_switch.value) { - change text validations { "email" } - } else { - change text validations { dynamicValidation('''maxLength ${max.value as Integer}''', null) } - } - - - - - transition - 200 - 200 - - auto - - - min - - editable - - - - max - - editable - - - - number - - editable - - - - text - - editable - - - - date - - editable - - - - number_valid_switch - - editable - - - - text_valid_switch - - editable - - - - - \ No newline at end of file diff --git a/src/test/resources/petriNets/dynamic_validations_performance_test.xml b/src/test/resources/petriNets/dynamic_validations_performance_test.xml deleted file mode 100644 index b6fa31f6112..00000000000 --- a/src/test/resources/petriNets/dynamic_validations_performance_test.xml +++ /dev/null @@ -1,3306 +0,0 @@ - - dynamic_validations_performance - dynamic_validations_performance - true - DVT - - - min - Min - - - max - Max - 5 - - - number - Number - - - inrange ${min.value as Integer},${max.value as Integer} - Number field validation message - - - - - text - Text - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_01 - Text 01 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_02 - Text 02 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_03 - Text 03 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_04 - Text 04 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_05 - Text 05 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_06 - Text 06 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_07 - Text 07 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_08 - Text 08 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_09 - Text 09 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_10 - Text 10 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_11 - Text 11 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_12 - Text 12 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_13 - Text 13 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_14 - Text 14 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_15 - Text 15 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_16 - Text 16 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_17 - Text 17 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_18 - Text 18 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_19 - Text 19 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_20 - Text 20 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_21 - Text 21 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_22 - Text 22 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_23 - Text 23 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_24 - Text 24 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_25 - Text 25 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_26 - Text 26 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_27 - Text 27 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_28 - Text 28 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_29 - Text 29 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_30 - Text 30 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_31 - Text 31 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_32 - Text 32 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_33 - Text 33 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_34 - Text 34 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_35 - Text 35 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_36 - Text 36 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_37 - Text 37 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_38 - Text 38 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_39 - Text 39 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_40 - Text 40 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_41 - Text 41 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_42 - Text 42 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_43 - Text 43 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_44 - Text 44 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_45 - Text 45 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_46 - Text 46 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_47 - Text 47 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_48 - Text 48 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_49 - Text 49 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_50 - Text 50 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_51 - Text 51 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_52 - Text 52 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_53 - Text 53 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_54 - Text 54 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_55 - Text 55 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_56 - Text 56 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_57 - Text 57 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_58 - Text 58 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_59 - Text 59 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_60 - Text 60 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_61 - Text 61 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_62 - Text 62 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_63 - Text 63 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_64 - Text 64 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_65 - Text 65 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_66 - Text 66 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_67 - Text 67 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_68 - Text 68 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_69 - Text 69 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_70 - Text 70 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_71 - Text 71 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_72 - Text 72 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_73 - Text 73 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_74 - Text 74 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_75 - Text 75 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_76 - Text 76 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_77 - Text 77 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_78 - Text 78 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_79 - Text 79 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_80 - Text 80 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_81 - Text 81 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_82 - Text 82 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_83 - Text 83 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_84 - Text 84 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_85 - Text 85 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_86 - Text 86 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_87 - Text 87 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_88 - Text 88 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_89 - Text 89 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_90 - Text 90 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_91 - Text 91 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_92 - Text 92 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_93 - Text 93 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_94 - Text 94 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_95 - Text 95 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_96 - Text 96 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_97 - Text 97 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_98 - Text 98 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - text_99 - Text 99 - - - maxLength ${max.value as Integer} - Text field validation message - - - - - number_01 - Text 01 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_02 - Text 02 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_03 - Text 03 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_04 - Text 04 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_05 - Text 05 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_06 - Text 06 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_07 - Text 07 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_08 - Text 08 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_09 - Text 09 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_10 - Text 10 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_11 - Text 11 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_12 - Text 12 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_13 - Text 13 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_14 - Text 14 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_15 - Text 15 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_16 - Text 16 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_17 - Text 17 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_18 - Text 18 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_19 - Text 19 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_20 - Text 20 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_21 - Text 21 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_22 - Text 22 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_23 - Text 23 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_24 - Text 24 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_25 - Text 25 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_26 - Text 26 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_27 - Text 27 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_28 - Text 28 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_29 - Text 29 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_30 - Text 30 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_31 - Text 31 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_32 - Text 32 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_33 - Text 33 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_34 - Text 34 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_35 - Text 35 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_36 - Text 36 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_37 - Text 37 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_38 - Text 38 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_39 - Text 39 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_40 - Text 40 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_41 - Text 41 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_42 - Text 42 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_43 - Text 43 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_44 - Text 44 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_45 - Text 45 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_46 - Text 46 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_47 - Text 47 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_48 - Text 48 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_49 - Text 49 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_50 - Text 50 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_51 - Text 51 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_52 - Text 52 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_53 - Text 53 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_54 - Text 54 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_55 - Text 55 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_56 - Text 56 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_57 - Text 57 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_58 - Text 58 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_59 - Text 59 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_60 - Text 60 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_61 - Text 61 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_62 - Text 62 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_63 - Text 63 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_64 - Text 64 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_65 - Text 65 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_66 - Text 66 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_67 - Text 67 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_68 - Text 68 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_69 - Text 69 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_70 - Text 70 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_71 - Text 71 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_72 - Text 72 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_73 - Text 73 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_74 - Text 74 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_75 - Text 75 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_76 - Text 76 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_77 - Text 77 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_78 - Text 78 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_79 - Text 79 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_80 - Text 80 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_81 - Text 81 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_82 - Text 82 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_83 - Text 83 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_84 - Text 84 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_85 - Text 85 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_86 - Text 86 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_87 - Text 87 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_88 - Text 88 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_89 - Text 89 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_90 - Text 90 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_91 - Text 91 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_92 - Text 92 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_93 - Text 93 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_94 - Text 94 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_95 - Text 95 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_96 - Text 96 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_97 - Text 97 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_98 - Text 98 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - number_99 - Text 99 - - - inrange 0,${max.value as Integer} - Text field validation message - - - - - - date - Date - - - between past,today-P${max.value as Integer}D - Date field validation message - - - - - - number_valid_switch - Switch - - - number_valid_switch: f.number_valid_switch, - number: f.number; - - if (number_valid_switch.value) { - change number validations { "odd" } - } else { - change number validations { new - com.netgrif.application.engine.petrinet.domain.dataset.Validation('''inrange - ${min.value as Integer},${max.value as Integer}''', true) } - } - - - - - text_valid_switch - Switch - - - text_valid_switch: f.text_valid_switch, - text: f.text; - - if (text_valid_switch.value) { - change text validations { "email" } - } else { - change text validations { - new com.netgrif.application.engine.petrinet.domain.dataset.Validation( - '''log.info("running");maxLength ${max.value as Integer}''', - new com.netgrif.application.engine.petrinet.domain.I18nString("")) - } - } - - - - - transition - 200 - 200 - - auto - - - min - - editable - - - - max - - editable - - - - number - - editable - - - - text - - editable - - - - date - - editable - - - - number_valid_switch - - editable - - - - text_valid_switch - - editable - - - - text_01 - - editable - - - - text_02 - - editable - - - - text_03 - - editable - - - - text_04 - - editable - - - - text_05 - - editable - - - - text_06 - - editable - - - - text_07 - - editable - - - - text_08 - - editable - - - - text_09 - - editable - - - - text_10 - - editable - - - - text_11 - - editable - - - - text_12 - - editable - - - - text_13 - - editable - - - - text_14 - - editable - - - - text_15 - - editable - - - - text_16 - - editable - - - - text_17 - - editable - - - - text_18 - - editable - - - - text_19 - - editable - - - - text_20 - - editable - - - - text_21 - - editable - - - - text_22 - - editable - - - - text_23 - - editable - - - - text_24 - - editable - - - - text_25 - - editable - - - - text_26 - - editable - - - - text_27 - - editable - - - - text_28 - - editable - - - - text_29 - - editable - - - - text_30 - - editable - - - - text_31 - - editable - - - - text_32 - - editable - - - - text_33 - - editable - - - - text_34 - - editable - - - - text_35 - - editable - - - - text_36 - - editable - - - - text_37 - - editable - - - - text_38 - - editable - - - - text_39 - - editable - - - - text_40 - - editable - - - - text_41 - - editable - - - - text_42 - - editable - - - - text_43 - - editable - - - - text_44 - - editable - - - - text_45 - - editable - - - - text_46 - - editable - - - - text_47 - - editable - - - - text_48 - - editable - - - - text_49 - - editable - - - - text_50 - - editable - - - - text_51 - - editable - - - - text_52 - - editable - - - - text_53 - - editable - - - - text_54 - - editable - - - - text_55 - - editable - - - - text_56 - - editable - - - - text_57 - - editable - - - - text_58 - - editable - - - - text_59 - - editable - - - - text_60 - - editable - - - - text_61 - - editable - - - - text_62 - - editable - - - - text_63 - - editable - - - - text_64 - - editable - - - - text_65 - - editable - - - - text_66 - - editable - - - - text_67 - - editable - - - - text_68 - - editable - - - - text_69 - - editable - - - - text_70 - - editable - - - - text_71 - - editable - - - - text_72 - - editable - - - - text_73 - - editable - - - - text_74 - - editable - - - - text_75 - - editable - - - - text_76 - - editable - - - - text_77 - - editable - - - - text_78 - - editable - - - - text_79 - - editable - - - - text_80 - - editable - - - - text_81 - - editable - - - - text_82 - - editable - - - - text_83 - - editable - - - - text_84 - - editable - - - - text_85 - - editable - - - - text_86 - - editable - - - - text_87 - - editable - - - - text_88 - - editable - - - - text_89 - - editable - - - - text_90 - - editable - - - - text_91 - - editable - - - - text_92 - - editable - - - - text_93 - - editable - - - - text_94 - - editable - - - - text_95 - - editable - - - - text_96 - - editable - - - - text_97 - - editable - - - - text_98 - - editable - - - - text_99 - - editable - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/test/resources/petriNets/dynamic_validations_performance_test_comparison.xml b/src/test/resources/petriNets/dynamic_validations_performance_test_comparison.xml deleted file mode 100644 index 9b1684aed87..00000000000 --- a/src/test/resources/petriNets/dynamic_validations_performance_test_comparison.xml +++ /dev/null @@ -1,3278 +0,0 @@ - - dynamic_validations_performance_comparison - dynamic_validations_performance_comparison - true - DVT - - - min - Min - - - max - Max - 5 - - - number - Number - - - inrange 0,10 - Number field validation message - - - - - text - Text - - - maxLength 10 - Text field validation message - - - - - text_01 - Text 01 - - - maxLength 10 - Text field validation message - - - - - text_02 - Text 02 - - - maxLength 10 - Text field validation message - - - - - text_03 - Text 03 - - - maxLength 10 - Text field validation message - - - - - text_04 - Text 04 - - - maxLength 10 - Text field validation message - - - - - text_05 - Text 05 - - - maxLength 10 - Text field validation message - - - - - text_06 - Text 06 - - - maxLength 10 - Text field validation message - - - - - text_07 - Text 07 - - - maxLength 10 - Text field validation message - - - - - text_08 - Text 08 - - - maxLength 10 - Text field validation message - - - - - text_09 - Text 09 - - - maxLength 10 - Text field validation message - - - - - text_10 - Text 10 - - - maxLength 10 - Text field validation message - - - - - text_11 - Text 11 - - - maxLength 10 - Text field validation message - - - - - text_12 - Text 12 - - - maxLength 10 - Text field validation message - - - - - text_13 - Text 13 - - - maxLength 10 - Text field validation message - - - - - text_14 - Text 14 - - - maxLength 10 - Text field validation message - - - - - text_15 - Text 15 - - - maxLength 10 - Text field validation message - - - - - text_16 - Text 16 - - - maxLength 10 - Text field validation message - - - - - text_17 - Text 17 - - - maxLength 10 - Text field validation message - - - - - text_18 - Text 18 - - - maxLength 10 - Text field validation message - - - - - text_19 - Text 19 - - - maxLength 10 - Text field validation message - - - - - text_20 - Text 20 - - - maxLength 10 - Text field validation message - - - - - text_21 - Text 21 - - - maxLength 10 - Text field validation message - - - - - text_22 - Text 22 - - - maxLength 10 - Text field validation message - - - - - text_23 - Text 23 - - - maxLength 10 - Text field validation message - - - - - text_24 - Text 24 - - - maxLength 10 - Text field validation message - - - - - text_25 - Text 25 - - - maxLength 10 - Text field validation message - - - - - text_26 - Text 26 - - - maxLength 10 - Text field validation message - - - - - text_27 - Text 27 - - - maxLength 10 - Text field validation message - - - - - text_28 - Text 28 - - - maxLength 10 - Text field validation message - - - - - text_29 - Text 29 - - - maxLength 10 - Text field validation message - - - - - text_30 - Text 30 - - - maxLength 10 - Text field validation message - - - - - text_31 - Text 31 - - - maxLength 10 - Text field validation message - - - - - text_32 - Text 32 - - - maxLength 10 - Text field validation message - - - - - text_33 - Text 33 - - - maxLength 10 - Text field validation message - - - - - text_34 - Text 34 - - - maxLength 10 - Text field validation message - - - - - text_35 - Text 35 - - - maxLength 10 - Text field validation message - - - - - text_36 - Text 36 - - - maxLength 10 - Text field validation message - - - - - text_37 - Text 37 - - - maxLength 10 - Text field validation message - - - - - text_38 - Text 38 - - - maxLength 10 - Text field validation message - - - - - text_39 - Text 39 - - - maxLength 10 - Text field validation message - - - - - text_40 - Text 40 - - - maxLength 10 - Text field validation message - - - - - text_41 - Text 41 - - - maxLength 10 - Text field validation message - - - - - text_42 - Text 42 - - - maxLength 10 - Text field validation message - - - - - text_43 - Text 43 - - - maxLength 10 - Text field validation message - - - - - text_44 - Text 44 - - - maxLength 10 - Text field validation message - - - - - text_45 - Text 45 - - - maxLength 10 - Text field validation message - - - - - text_46 - Text 46 - - - maxLength 10 - Text field validation message - - - - - text_47 - Text 47 - - - maxLength 10 - Text field validation message - - - - - text_48 - Text 48 - - - maxLength 10 - Text field validation message - - - - - text_49 - Text 49 - - - maxLength 10 - Text field validation message - - - - - text_50 - Text 50 - - - maxLength 10 - Text field validation message - - - - - text_51 - Text 51 - - - maxLength 10 - Text field validation message - - - - - text_52 - Text 52 - - - maxLength 10 - Text field validation message - - - - - text_53 - Text 53 - - - maxLength 10 - Text field validation message - - - - - text_54 - Text 54 - - - maxLength 10 - Text field validation message - - - - - text_55 - Text 55 - - - maxLength 10 - Text field validation message - - - - - text_56 - Text 56 - - - maxLength 10 - Text field validation message - - - - - text_57 - Text 57 - - - maxLength 10 - Text field validation message - - - - - text_58 - Text 58 - - - maxLength 10 - Text field validation message - - - - - text_59 - Text 59 - - - maxLength 10 - Text field validation message - - - - - text_60 - Text 60 - - - maxLength 10 - Text field validation message - - - - - text_61 - Text 61 - - - maxLength 10 - Text field validation message - - - - - text_62 - Text 62 - - - maxLength 10 - Text field validation message - - - - - text_63 - Text 63 - - - maxLength 10 - Text field validation message - - - - - text_64 - Text 64 - - - maxLength 10 - Text field validation message - - - - - text_65 - Text 65 - - - maxLength 10 - Text field validation message - - - - - text_66 - Text 66 - - - maxLength 10 - Text field validation message - - - - - text_67 - Text 67 - - - maxLength 10 - Text field validation message - - - - - text_68 - Text 68 - - - maxLength 10 - Text field validation message - - - - - text_69 - Text 69 - - - maxLength 10 - Text field validation message - - - - - text_70 - Text 70 - - - maxLength 10 - Text field validation message - - - - - text_71 - Text 71 - - - maxLength 10 - Text field validation message - - - - - text_72 - Text 72 - - - maxLength 10 - Text field validation message - - - - - text_73 - Text 73 - - - maxLength 10 - Text field validation message - - - - - text_74 - Text 74 - - - maxLength 10 - Text field validation message - - - - - text_75 - Text 75 - - - maxLength 10 - Text field validation message - - - - - text_76 - Text 76 - - - maxLength 10 - Text field validation message - - - - - text_77 - Text 77 - - - maxLength 10 - Text field validation message - - - - - text_78 - Text 78 - - - maxLength 10 - Text field validation message - - - - - text_79 - Text 79 - - - maxLength 10 - Text field validation message - - - - - text_80 - Text 80 - - - maxLength 10 - Text field validation message - - - - - text_81 - Text 81 - - - maxLength 10 - Text field validation message - - - - - text_82 - Text 82 - - - maxLength 10 - Text field validation message - - - - - text_83 - Text 83 - - - maxLength 10 - Text field validation message - - - - - text_84 - Text 84 - - - maxLength 10 - Text field validation message - - - - - text_85 - Text 85 - - - maxLength 10 - Text field validation message - - - - - text_86 - Text 86 - - - maxLength 10 - Text field validation message - - - - - text_87 - Text 87 - - - maxLength 10 - Text field validation message - - - - - text_88 - Text 88 - - - maxLength 10 - Text field validation message - - - - - text_89 - Text 89 - - - maxLength 10 - Text field validation message - - - - - text_90 - Text 90 - - - maxLength 10 - Text field validation message - - - - - text_91 - Text 91 - - - maxLength 10 - Text field validation message - - - - - text_92 - Text 92 - - - maxLength 10 - Text field validation message - - - - - text_93 - Text 93 - - - maxLength 10 - Text field validation message - - - - - text_94 - Text 94 - - - maxLength 10 - Text field validation message - - - - - text_95 - Text 95 - - - maxLength 10 - Text field validation message - - - - - text_96 - Text 96 - - - maxLength 10 - Text field validation message - - - - - text_97 - Text 97 - - - maxLength 10 - Text field validation message - - - - - text_98 - Text 98 - - - maxLength 10 - Text field validation message - - - - - text_99 - Text 99 - - - maxLength 10 - Text field validation message - - - - - number_01 - Text 01 - - - inrange 0,5 - Text field validation message - - - - - number_02 - Text 02 - - - inrange 0,5 - Text field validation message - - - - - number_03 - Text 03 - - - inrange 0,5 - Text field validation message - - - - - number_04 - Text 04 - - - inrange 0,5 - Text field validation message - - - - - number_05 - Text 05 - - - inrange 0,5 - Text field validation message - - - - - number_06 - Text 06 - - - inrange 0,5 - Text field validation message - - - - - number_07 - Text 07 - - - inrange 0,5 - Text field validation message - - - - - number_08 - Text 08 - - - inrange 0,5 - Text field validation message - - - - - number_09 - Text 09 - - - inrange 0,5 - Text field validation message - - - - - number_10 - Text 10 - - - inrange 0,5 - Text field validation message - - - - - number_11 - Text 11 - - - inrange 0,5 - Text field validation message - - - - - number_12 - Text 12 - - - inrange 0,5 - Text field validation message - - - - - number_13 - Text 13 - - - inrange 0,5 - Text field validation message - - - - - number_14 - Text 14 - - - inrange 0,5 - Text field validation message - - - - - number_15 - Text 15 - - - inrange 0,5 - Text field validation message - - - - - number_16 - Text 16 - - - inrange 0,5 - Text field validation message - - - - - number_17 - Text 17 - - - inrange 0,5 - Text field validation message - - - - - number_18 - Text 18 - - - inrange 0,5 - Text field validation message - - - - - number_19 - Text 19 - - - inrange 0,5 - Text field validation message - - - - - number_20 - Text 20 - - - inrange 0,5 - Text field validation message - - - - - number_21 - Text 21 - - - inrange 0,5 - Text field validation message - - - - - number_22 - Text 22 - - - inrange 0,5 - Text field validation message - - - - - number_23 - Text 23 - - - inrange 0,5 - Text field validation message - - - - - number_24 - Text 24 - - - inrange 0,5 - Text field validation message - - - - - number_25 - Text 25 - - - inrange 0,5 - Text field validation message - - - - - number_26 - Text 26 - - - inrange 0,5 - Text field validation message - - - - - number_27 - Text 27 - - - inrange 0,5 - Text field validation message - - - - - number_28 - Text 28 - - - inrange 0,5 - Text field validation message - - - - - number_29 - Text 29 - - - inrange 0,5 - Text field validation message - - - - - number_30 - Text 30 - - - inrange 0,5 - Text field validation message - - - - - number_31 - Text 31 - - - inrange 0,5 - Text field validation message - - - - - number_32 - Text 32 - - - inrange 0,5 - Text field validation message - - - - - number_33 - Text 33 - - - inrange 0,5 - Text field validation message - - - - - number_34 - Text 34 - - - inrange 0,5 - Text field validation message - - - - - number_35 - Text 35 - - - inrange 0,5 - Text field validation message - - - - - number_36 - Text 36 - - - inrange 0,5 - Text field validation message - - - - - number_37 - Text 37 - - - inrange 0,5 - Text field validation message - - - - - number_38 - Text 38 - - - inrange 0,5 - Text field validation message - - - - - number_39 - Text 39 - - - inrange 0,5 - Text field validation message - - - - - number_40 - Text 40 - - - inrange 0,5 - Text field validation message - - - - - number_41 - Text 41 - - - inrange 0,5 - Text field validation message - - - - - number_42 - Text 42 - - - inrange 0,5 - Text field validation message - - - - - number_43 - Text 43 - - - inrange 0,5 - Text field validation message - - - - - number_44 - Text 44 - - - inrange 0,5 - Text field validation message - - - - - number_45 - Text 45 - - - inrange 0,5 - Text field validation message - - - - - number_46 - Text 46 - - - inrange 0,5 - Text field validation message - - - - - number_47 - Text 47 - - - inrange 0,5 - Text field validation message - - - - - number_48 - Text 48 - - - inrange 0,5 - Text field validation message - - - - - number_49 - Text 49 - - - inrange 0,5 - Text field validation message - - - - - number_50 - Text 50 - - - inrange 0,5 - Text field validation message - - - - - number_51 - Text 51 - - - inrange 0,5 - Text field validation message - - - - - number_52 - Text 52 - - - inrange 0,5 - Text field validation message - - - - - number_53 - Text 53 - - - inrange 0,5 - Text field validation message - - - - - number_54 - Text 54 - - - inrange 0,5 - Text field validation message - - - - - number_55 - Text 55 - - - inrange 0,5 - Text field validation message - - - - - number_56 - Text 56 - - - inrange 0,5 - Text field validation message - - - - - number_57 - Text 57 - - - inrange 0,5 - Text field validation message - - - - - number_58 - Text 58 - - - inrange 0,5 - Text field validation message - - - - - number_59 - Text 59 - - - inrange 0,5 - Text field validation message - - - - - number_60 - Text 60 - - - inrange 0,5 - Text field validation message - - - - - number_61 - Text 61 - - - inrange 0,5 - Text field validation message - - - - - number_62 - Text 62 - - - inrange 0,5 - Text field validation message - - - - - number_63 - Text 63 - - - inrange 0,5 - Text field validation message - - - - - number_64 - Text 64 - - - inrange 0,5 - Text field validation message - - - - - number_65 - Text 65 - - - inrange 0,5 - Text field validation message - - - - - number_66 - Text 66 - - - inrange 0,5 - Text field validation message - - - - - number_67 - Text 67 - - - inrange 0,5 - Text field validation message - - - - - number_68 - Text 68 - - - inrange 0,5 - Text field validation message - - - - - number_69 - Text 69 - - - inrange 0,5 - Text field validation message - - - - - number_70 - Text 70 - - - inrange 0,5 - Text field validation message - - - - - number_71 - Text 71 - - - inrange 0,5 - Text field validation message - - - - - number_72 - Text 72 - - - inrange 0,5 - Text field validation message - - - - - number_73 - Text 73 - - - inrange 0,5 - Text field validation message - - - - - number_74 - Text 74 - - - inrange 0,5 - Text field validation message - - - - - number_75 - Text 75 - - - inrange 0,5 - Text field validation message - - - - - number_76 - Text 76 - - - inrange 0,5 - Text field validation message - - - - - number_77 - Text 77 - - - inrange 0,5 - Text field validation message - - - - - number_78 - Text 78 - - - inrange 0,5 - Text field validation message - - - - - number_79 - Text 79 - - - inrange 0,5 - Text field validation message - - - - - number_80 - Text 80 - - - inrange 0,5 - Text field validation message - - - - - number_81 - Text 81 - - - inrange 0,5 - Text field validation message - - - - - number_82 - Text 82 - - - inrange 0,5 - Text field validation message - - - - - number_83 - Text 83 - - - inrange 0,5 - Text field validation message - - - - - number_84 - Text 84 - - - inrange 0,5 - Text field validation message - - - - - number_85 - Text 85 - - - inrange 0,5 - Text field validation message - - - - - number_86 - Text 86 - - - inrange 0,5 - Text field validation message - - - - - number_87 - Text 87 - - - inrange 0,5 - Text field validation message - - - - - number_88 - Text 88 - - - inrange 0,5 - Text field validation message - - - - - number_89 - Text 89 - - - inrange 0,5 - Text field validation message - - - - - number_90 - Text 90 - - - inrange 0,5 - Text field validation message - - - - - number_91 - Text 91 - - - inrange 0,5 - Text field validation message - - - - - number_92 - Text 92 - - - inrange 0,5 - Text field validation message - - - - - number_93 - Text 93 - - - inrange 0,5 - Text field validation message - - - - - number_94 - Text 94 - - - inrange 0,5 - Text field validation message - - - - - number_95 - Text 95 - - - inrange 0,5 - Text field validation message - - - - - number_96 - Text 96 - - - inrange 0,5 - Text field validation message - - - - - number_97 - Text 97 - - - inrange 0,5 - Text field validation message - - - - - number_98 - Text 98 - - - inrange 0,5 - Text field validation message - - - - - number_99 - Text 99 - - - inrange 0,5 - Text field validation message - - - - - - date - Date - - - between past,today-P1D - Date field validation message - - - - - - number_valid_switch - Switch - - - - text_valid_switch - Switch - - - - transition - 200 - 200 - - auto - - - min - - editable - - - - max - - editable - - - - number - - editable - - - - text - - editable - - - - date - - editable - - - - number_valid_switch - - editable - - - - text_valid_switch - - editable - - - - text_01 - - editable - - - - text_02 - - editable - - - - text_03 - - editable - - - - text_04 - - editable - - - - text_05 - - editable - - - - text_06 - - editable - - - - text_07 - - editable - - - - text_08 - - editable - - - - text_09 - - editable - - - - text_10 - - editable - - - - text_11 - - editable - - - - text_12 - - editable - - - - text_13 - - editable - - - - text_14 - - editable - - - - text_15 - - editable - - - - text_16 - - editable - - - - text_17 - - editable - - - - text_18 - - editable - - - - text_19 - - editable - - - - text_20 - - editable - - - - text_21 - - editable - - - - text_22 - - editable - - - - text_23 - - editable - - - - text_24 - - editable - - - - text_25 - - editable - - - - text_26 - - editable - - - - text_27 - - editable - - - - text_28 - - editable - - - - text_29 - - editable - - - - text_30 - - editable - - - - text_31 - - editable - - - - text_32 - - editable - - - - text_33 - - editable - - - - text_34 - - editable - - - - text_35 - - editable - - - - text_36 - - editable - - - - text_37 - - editable - - - - text_38 - - editable - - - - text_39 - - editable - - - - text_40 - - editable - - - - text_41 - - editable - - - - text_42 - - editable - - - - text_43 - - editable - - - - text_44 - - editable - - - - text_45 - - editable - - - - text_46 - - editable - - - - text_47 - - editable - - - - text_48 - - editable - - - - text_49 - - editable - - - - text_50 - - editable - - - - text_51 - - editable - - - - text_52 - - editable - - - - text_53 - - editable - - - - text_54 - - editable - - - - text_55 - - editable - - - - text_56 - - editable - - - - text_57 - - editable - - - - text_58 - - editable - - - - text_59 - - editable - - - - text_60 - - editable - - - - text_61 - - editable - - - - text_62 - - editable - - - - text_63 - - editable - - - - text_64 - - editable - - - - text_65 - - editable - - - - text_66 - - editable - - - - text_67 - - editable - - - - text_68 - - editable - - - - text_69 - - editable - - - - text_70 - - editable - - - - text_71 - - editable - - - - text_72 - - editable - - - - text_73 - - editable - - - - text_74 - - editable - - - - text_75 - - editable - - - - text_76 - - editable - - - - text_77 - - editable - - - - text_78 - - editable - - - - text_79 - - editable - - - - text_80 - - editable - - - - text_81 - - editable - - - - text_82 - - editable - - - - text_83 - - editable - - - - text_84 - - editable - - - - text_85 - - editable - - - - text_86 - - editable - - - - text_87 - - editable - - - - text_88 - - editable - - - - text_89 - - editable - - - - text_90 - - editable - - - - text_91 - - editable - - - - text_92 - - editable - - - - text_93 - - editable - - - - text_94 - - editable - - - - text_95 - - editable - - - - text_96 - - editable - - - - text_97 - - editable - - - - text_98 - - editable - - - - text_99 - - editable - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/test/resources/petriNets/filter_api_test.xml b/src/test/resources/petriNets/filter_api_test.xml index 37da147acbe..1747419eece 100644 --- a/src/test/resources/petriNets/filter_api_test.xml +++ b/src/test/resources/petriNets/filter_api_test.xml @@ -1,136 +1,48 @@ - + filter_api_test - FTT + 1.0.0 filter_api_test device_hub true true - false - - - role_1 - Role 1 - - - - role_2 - Role 2 - - + + FTT + upload - + + - - - - menu_stringId - - </data> - <data type="text"> - <id>filter_stringId</id> - <title/> - </data> - - <data type="text"> - <id>query</id> - <title/> - <init>processIdentifier:"filter_api_test"</init> - </data> - <data type="text"> - <id>icon</id> - <title/> - <init>device_hub</init> - </data> - <data type="text"> - <id>uri</id> - <title/> - </data> + <caseEvents/> + <role> + <id>role_1</id> + <title>Role 1 + + + role_2 + Role 2 + allowed_nets </data> - <data type="text"> - <id>title</id> - <title/> - </data> - <data type="text"> - <id>identifier</id> - <title/> - </data> - <data type="text"> - <id>group</id> - <title>Skupina - - - - create_filter_and_menu - create filter and menu - - - - - group: f.group, - menu_stringId: f.menu_stringId, - filter_stringId: f.filter_stringId, - uri: f.uri, - title: f.title, - allowed_nets: f.allowed_nets, - query: f.query, - identifier: f.identifier, - icon: f.icon; - - def filter = createCaseFilter(title.rawValue, query.rawValue, allowed_nets.rawValue.split(",") as List, icon.rawValue) - def item - - if (group.value) { - item = createMenuItem( - uri.rawValue, - identifier.rawValue, - filter, - group.rawValue, - ["role_1": "filter_api_test"], - [:] - ) - } else { - item = createMenuItem( - uri.rawValue, - identifier.rawValue, - filter, - ["role_1": "filter_api_test"], - [:] - ) - } - change menu_stringId value { item.stringId } - change filter_stringId value { filter.stringId } - - - - change_filter_and_menu change filter and menu - + set_event_1 - - uri: f.uri, - title: f.title, - allowed_nets: f.allowed_nets, - query: f.query, - group: f.group, - identifier: f.identifier, - icon: f.icon; - + + - delete_filter_and_menu - delete filter and menu - + create_filter_and_menu + create filter and menu + set_event_0 - - menu_stringId: f.menu_stringId, - identifier: f.identifier; + + @@ -179,52 +94,59 @@ create_filter_in_group create filter in group - + set_event_3 - - menu_stringId: f.menu_stringId, - filter_stringId: f.filter_stringId, - uri: f.uri, - title: f.title, - allowed_nets: f.allowed_nets, - query: f.query, - group: f.group, - identifier: f.identifier, - icon: f.icon; + + - + + delete_filter_and_menu + delete filter and menu + + set_event_2 + + + + + + + + + filter_stringId + + </data> <data type="button"> <id>find_filter</id> <title>find filter - + set_event_4 - - title: f.title, - found_filter: f.found_filter; - + + @@ -233,17 +155,39 @@ found_filter found filter - + + group + Skupina + + + icon + + <init>device_hub</init> + </data> + <data type="text"> + <id>identifier</id> + <title/> + </data> + <data type="text"> + <id>menu_stringId</id> + <title/> + </data> + <data type="text"> + <id>move_dest_uri</id> + <title>found filter + + + move_folder_path + Folder item path to find + move_item move item + set_event_5 - - move_dest_uri: f.move_dest_uri, - move_item_id: f.move_item_id, - move_folder_path: f.move_folder_path; - + + - - move_dest_uri - found filter - move_item_id View item id to find - move_folder_path - Folder item path to find + query + + <init>processIdentifier:"filter_api_test"</init> + </data> + <data type="text"> + <id>title</id> + <title/> + </data> + <data type="text"> + <id>uri</id> + <title/> </data> - <transition> <id>t1</id> <x>700</x> <y>180</y> - <label>TEST API</label> - <event type="assign"> - <id>t1_assign</id> - </event> - <event type="finish"> - <id>t1_finish</id> - </event> - <event type="cancel"> - <id>t1_cancel</id> - </event> - <event type="delegate"> - <id>t1_delegate</id> - </event> + <title>TEST API - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/function_overloading.xml b/src/test/resources/petriNets/function_overloading.xml index e0be12ab54a..b04fb96805e 100644 --- a/src/test/resources/petriNets/function_overloading.xml +++ b/src/test/resources/petriNets/function_overloading.xml @@ -1,33 +1,40 @@ - - + function_overloading - FOF + 1.0.0 Test - + false + false + + FOF + - { String x, String y -> - "$x $y" - } + + "$x $y" + } + ]]> - { Double x, Double y -> - x * y - } + + x * y + } + ]]> - - number Number - - number: f.number, - number2: f.number2, - text: f.text; - - change number2 value { function_overloading.overloadingTest(number.rawValue, number.rawValue) } - change text value { overloadingTest(number.rawValue as String, number.rawValue as String).toString() } - + + number_set + + + + + + number2 @@ -37,13 +44,13 @@ text Number - - 1 + t1 0 0 - + Test + + t1_flex + - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/function_overloading_fail.xml b/src/test/resources/petriNets/function_overloading_fail.xml index e35e537652d..bdd13c8b625 100644 --- a/src/test/resources/petriNets/function_overloading_fail.xml +++ b/src/test/resources/petriNets/function_overloading_fail.xml @@ -1,33 +1,37 @@ - - + function_overloading_fail - FOF + 1.0.0 Test - + false + false + + FOF + - { Double x, Double y -> - x * y - } + + x * y + } + ]]> - { Double x, Double y -> - x + y - } + + x + y + } + ]]> - - number Number - - 1 + t1 0 0 - + Test + + t1_flex + - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/function_overloading_fail_v2.xml b/src/test/resources/petriNets/function_overloading_fail_v2.xml index edb1a05ff26..dba019d60a9 100644 --- a/src/test/resources/petriNets/function_overloading_fail_v2.xml +++ b/src/test/resources/petriNets/function_overloading_fail_v2.xml @@ -1,33 +1,37 @@ - - + function_overloading_fail - FOF + 1.0.0 Test - + false + false + + FOF + - { Double x, Double y -> - x * y - } + + x * y + } + ]]> - { Double x, Double y -> - x + y - } + + x + y + } + ]]> - - number Number - - 1 + t1 0 0 - + Test + + t1_flex + - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/function_overloading_v2.xml b/src/test/resources/petriNets/function_overloading_v2.xml index c59c2348ddb..95246e996ab 100644 --- a/src/test/resources/petriNets/function_overloading_v2.xml +++ b/src/test/resources/petriNets/function_overloading_v2.xml @@ -1,33 +1,40 @@ - - + function_overloading - FOF + 1.0.0 Test - + false + false + + FOF + - { String x, String y -> - "$x $y" - } + + "$x $y" + } + ]]> - { Double x, Double y -> - x * y - } + + x * y + } + ]]> - - number Number - - number: f.number, - number2: f.number2, - text: f.text; - - change number2 value { overloadingTest(number.rawValue, number.rawValue) } - change text value { overloadingTest("${number.rawValue}" as String, "${number.rawValue}" as String) } - + + number_set + + + + + + number2 @@ -37,13 +44,13 @@ text Number - - 1 + t1 0 0 - + Test + + t1_flex + - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/function_res.xml b/src/test/resources/petriNets/function_res.xml index 7de4deb4a3d..7dbd92c7e27 100644 --- a/src/test/resources/petriNets/function_res.xml +++ b/src/test/resources/petriNets/function_res.xml @@ -1,44 +1,53 @@ - - + function_res - SFR + 1.0.0 Test - - - { com.netgrif.application.engine.auth.domain.User user -> + false + false + + SFR + + + + return x + y + } + ]]> + + + if (user != null) { registrationService.encodeUserPassword(user) userService.save(user) } } + ]]> - - { def x, def y -> - return x + y - } - - - number Number - - 1 + t1 0 0 - - - 0 - flow - - number - editable - - + Test + + t1_flex + + + number + + editable + + + + 0 + 0 + 1 + + + - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/function_res_v2.xml b/src/test/resources/petriNets/function_res_v2.xml index 9cfbbf97e1e..704ddf20404 100644 --- a/src/test/resources/petriNets/function_res_v2.xml +++ b/src/test/resources/petriNets/function_res_v2.xml @@ -1,41 +1,50 @@ - - + function_res - SFR + 1.0.0 Test - - - { def x, def y -> - return x * y - } + false + false + + SFR + + + + return x * y + } + ]]> - - { def fieldId, def newValue -> - change useCase.dataSet.get(fieldId) value { newValue } - } + + + change useCase.dataSet.get(fieldId) value { newValue } + } + ]]> - - number Number - - 1 + t1 0 0 - - - 0 - flow - - number - editable - - + Test + + t1_flex + + + number + + editable + + + + 0 + 0 + 1 + + + - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/function_test.xml b/src/test/resources/petriNets/function_test.xml index b68b5e0dd72..23b34a0b4c6 100644 --- a/src/test/resources/petriNets/function_test.xml +++ b/src/test/resources/petriNets/function_test.xml @@ -1,151 +1,214 @@ - - + function_test - SFT + 1.0.0 Test - + false + false + + SFT + admin - Admin + Admin user - User + User - - { def fields, def transitionIds, def condition, behavior = editable, behavior2 = required -> - if (evaluateCompactedCondition(condition)) { - transitionIds.each { transitionId -> - fields.each { - behaveField(it as String, transitionId, behavior as Closure) - behaveField(it as String, transitionId, behavior2 as Closure) - } - } - } else { - transitionIds.each { transitionId -> - fields.each { - behaveField(it as String, transitionId, hidden as Closure) - behaveField(it as String, transitionId, optional as Closure) - } - } - } - } - - { def fieldId, def transitionId, def behavior -> - make useCase.dataSet.get(fieldId), behavior on useCase.petriNet.transitions[transitionId] when { true } - } + + make useCase.dataSet.get(fieldId), behavior on useCase.process.transitions[transitionId] when { true } + } + ]]> - { def compactedCondition -> - for (def disjunction = compactedCondition.iterator(); disjunction.hasNext();) { - if (!evaluateCompactedDisjunction(disjunction.next())) - return false - } - return true - } + + for (def disjunction = compactedCondition.iterator(); disjunction.hasNext();) { + if (!evaluateCompactedDisjunction(disjunction.next())) + return false + } + return true + } + ]]> - { def compactedDisjunction -> - String fieldId = compactedDisjunction.get(0) - String fieldType = compactedDisjunction.get(1) - - if (compactedDisjunction.size() == 2) { - // empty condition - return ((useCase.dataSet[fieldId].value as String)?.isEmpty() as boolean || useCase.dataSet[fieldId]?.value == null) as boolean - } else { - if (fieldType == "E" || fieldType == "B") - return compactedDisjunction[2..compactedDisjunction.size() - 1].contains(useCase.dataSet[fieldId].value as String) as boolean - else if (fieldType == "M") { - return ![0, null].contains((useCase.dataSet[fieldId].value as Set)?.stream()?.map { str -> str as String }?.collect(Collectors.toSet())?.intersect(compactedDisjunction[2..compactedDisjunction.size() - 1])?.size()) as boolean - } else if (fieldType == "BTN") { - if (useCase.dataSet[fieldId].value == null) return false - return compactedDisjunction[2..compactedDisjunction.size() - 1].contains((useCase.dataSet[fieldId]?.value as int) % 2 as String) as Boolean - } else return false - } - } + + String fieldId = compactedDisjunction.get(0) + String fieldType = compactedDisjunction.get(1) + if (compactedDisjunction.size() == 2) { + // empty condition + return ((useCase.dataSet[fieldId].value as String)?.isEmpty() as boolean || useCase.dataSet[fieldId]?.value == null) as boolean + } else { + if (fieldType == "E" || fieldType == "B") + return compactedDisjunction[2..compactedDisjunction.size() - 1].contains(useCase.dataSet[fieldId].value as String) as boolean + else if (fieldType == "M") { + return ![0, null].contains((useCase.dataSet[fieldId].value as Set)?.stream()?.map { str -> str as String }?.collect(Collectors.toSet())?.intersect(compactedDisjunction[2..compactedDisjunction.size() - 1])?.size()) as boolean + } else if (fieldType == "BTN") { + if (useCase.dataSet[fieldId].value == null) return false + return compactedDisjunction[2..compactedDisjunction.size() - 1].contains((useCase.dataSet[fieldId]?.value as int) % 2 as String) as Boolean + } else return false + } + } + ]]> - { def foo -> - return foo - } + + return foo + } + ]]> - - - text - Text - - text: f.text; - - function_test.foo(text.value) - - - - number - Number - - number: f.number, - number2: f.number2; - - change number2 value { function_res.calculate(number.rawValue, number.rawValue)} - - - - number3 - Number3 - - number2: f.number2; - - change number2 value { nonExistingFunction() } - + + + if (evaluateCompactedCondition(condition)) { + transitionIds.each { transitionId -> + fields.each { + behaveField(it as String, transitionId, behavior as Closure) + behaveField(it as String, transitionId, behavior2 as Closure) + } + } + } else { + transitionIds.each { transitionId -> + fields.each { + behaveField(it as String, transitionId, hidden as Closure) + behaveField(it as String, transitionId, optional as Closure) + } + } + } + } + ]]> + + + createUser + Boolean + false + + createUser_set + + + + + + enum Enum - ano - nie - - showFields(["number"], ["1"], [["enum", "E", "ano"]]) - + + + + + + enum_set + + + + + + + + + number + Number + + number_set + + + + + + number2 Number - - createUser - Boolean - false - - def user = new com.netgrif.application.engine.auth.domain.User("test@test.com", "password", "test", "test") - user.state = com.netgrif.application.engine.auth.domain.UserState.ACTIVE - function_res.createUser(user) - + + number3 + Number3 + + number3_set + + + + + + + + + text + Text + + text_set + + + + + + - - 1 + t1 0 0 - - - 0 - flow - - number - editable - - - number2 - editable - - - enum - editable - - + Test + + t1_flex + + + number + + editable + + + + 0 + 0 + 1 + + + + + number2 + + editable + + + + 0 + 0 + 1 + + + + + enum + + editable + + + + 0 + 0 + 1 + + + - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/function_test_v2.xml b/src/test/resources/petriNets/function_test_v2.xml index d3397b855b6..49802d92846 100644 --- a/src/test/resources/petriNets/function_test_v2.xml +++ b/src/test/resources/petriNets/function_test_v2.xml @@ -1,118 +1,137 @@ - - + function_test - SFT + 1.0.0 Test - + false + false + + SFT + admin - Admin + Admin user - User + User - - { def fields, def transitionIds, def condition, behavior = editable, behavior2 = required -> - if (evaluateCompactedCondition(condition)) { - transitionIds.each { transitionId -> - fields.each { - behaveField(it as String, transitionId, behavior as Closure) - behaveField(it as String, transitionId, behavior2 as Closure) - } - - } - } else { - transitionIds.each { transitionId -> - fields.each { - behaveField(it as String, transitionId, hidden as Closure) - behaveField(it as String, transitionId, optional as Closure) - } - } - } - } - - { def fieldId, def transitionId, def behavior -> - make useCase.getField(fieldId), behavior on useCase.petriNet.transitions[transitionId] when { true } - } + + make useCase.getField(fieldId), behavior on useCase.petriNet.transitions[transitionId] when { true } + } + ]]> - { def compactedCondition -> - for (def disjunction = compactedCondition.iterator(); disjunction.hasNext();) { - if (!evaluateCompactedDisjunction(disjunction.next())) - return false - } - return true - } + + for (def disjunction = compactedCondition.iterator(); disjunction.hasNext();) { + if (!evaluateCompactedDisjunction(disjunction.next())) + return false + } + return true + } + ]]> - { def compactedDisjunction -> - String fieldId = compactedDisjunction.get(0) - String fieldType = compactedDisjunction.get(1) - - if (compactedDisjunction.size() == 2) { - // empty condition - return ((useCase.dataSet[fieldId].value as String)?.isEmpty() as boolean || useCase.dataSet[fieldId]?.value == null) as boolean - } else { - if (fieldType == "E" || fieldType == "B") - return compactedDisjunction[2..compactedDisjunction.size() - 1].contains(useCase.dataSet[fieldId].value as String) as boolean - else if (fieldType == "M") { - return ![0, null].contains((useCase.dataSet[fieldId].value as Set)?.stream()?.map { str -> str as String }?.collect(Collectors.toSet())?.intersect(compactedDisjunction[2..compactedDisjunction.size() - 1])?.size()) as boolean - } else if (fieldType == "BTN") { - if (useCase.dataSet[fieldId].value == null) return false - return compactedDisjunction[2..compactedDisjunction.size() - 1].contains((useCase.dataSet[fieldId]?.value as int) % 2 as String) as Boolean - } else return false - } - } + + String fieldId = compactedDisjunction.get(0) + String fieldType = compactedDisjunction.get(1) + if (compactedDisjunction.size() == 2) { + // empty condition + return ((useCase.dataSet[fieldId].value as String)?.isEmpty() as boolean || useCase.dataSet[fieldId]?.value == null) as boolean + } else { + if (fieldType == "E" || fieldType == "B") + return compactedDisjunction[2..compactedDisjunction.size() - 1].contains(useCase.dataSet[fieldId].value as String) as boolean + else if (fieldType == "M") { + return ![0, null].contains((useCase.dataSet[fieldId].value as Set)?.stream()?.map { str -> str as String }?.collect(Collectors.toSet())?.intersect(compactedDisjunction[2..compactedDisjunction.size() - 1])?.size()) as boolean + } else if (fieldType == "BTN") { + if (useCase.dataSet[fieldId].value == null) return false + return compactedDisjunction[2..compactedDisjunction.size() - 1].contains((useCase.dataSet[fieldId]?.value as int) % 2 as String) as Boolean + } else return false + } + } + ]]> - - - text - Text - - text: f.text; - - function_test.foo(text.value) - - - - number - Number + + + if (evaluateCompactedCondition(condition)) { + transitionIds.each { transitionId -> + fields.each { + behaveField(it as String, transitionId, behavior as Closure) + behaveField(it as String, transitionId, behavior2 as Closure) + } + } + } else { + transitionIds.each { transitionId -> + fields.each { + behaveField(it as String, transitionId, hidden as Closure) + behaveField(it as String, transitionId, optional as Closure) + } + } + } + } + ]]> + + + createUser + Boolean + false + + createUser_set + + + + + + enum Enum - ano - nie - - showFields(["number"], ["0"], [["enum", "E", "ano"]]) - + + + + + + enum_set + + + + + + - number2 + number Number - - createUser - Boolean - false - - def user = new com.netgrif.application.engine.auth.domain.User("test@test.com", "password", "test", "test") - user.state = com.netgrif.application.engine.auth.domain.UserState.ACTIVE - function_res.createUser(user) - + + number2 + Number - - updateOtherField - Boolean - false - - toBeUpdatedInternally: f.toBeUpdatedInternally; - function_res.updateUseCaseFieldValue("toBeUpdated", 1) - change toBeUpdatedInternally value { (useCase.dataSet.get("toBeUpdated").rawValue as Double) + 1.0 } - + + text + Text + + text_set + + + + + + toBeUpdated @@ -122,25 +141,55 @@ toBeUpdatedInternally Number - + + updateOtherField + Boolean + false + + updateOtherField_set + + + + + + + - 0 + t0 0 0 - - - 0 - flow - - number - editable - - - enum - editable - - + Test + + t0_flex + + + number + + editable + + + + 0 + 0 + 1 + + + + + enum + + editable + + + + 0 + 0 + 1 + + + - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/groovy_shell_test.xml b/src/test/resources/petriNets/groovy_shell_test.xml index 51d41498cbe..66bdaa54dea 100644 --- a/src/test/resources/petriNets/groovy_shell_test.xml +++ b/src/test/resources/petriNets/groovy_shell_test.xml @@ -1,53 +1,54 @@ - - - new_model - NEW - New Model - true - false - - - - newRole_1 - - - - - userService.groovyShellTestMethod("String", new I18nString("I18nString")) + + new_model + 1.0.0 + New Model + true + false + + NEW + + + newRole_1 + + <event type="assign"> + <id>assign_event_0</id> + <actions phase="pre"> + <action id="action_0"> + <![CDATA[ + userService.groovyShellTestMethod("String", new I18nString("I18nString")) + ]]> </action> - </actions> - </event> - </role> - <!-- PROCESS ROLE REFS --> - <!-- PROCESS USER REFS --> - <!-- DATA --> - <data type="text"> - <id>newVariable_1</id> - <title> - - validation("String", new I18nString("I18nString")) + + + + + newVariable_1 + + <init dynamic="true"> + <![CDATA[ + validation("String", null, null, new I18nString("I18nString")) return "value" - </init> - </data> - <!-- I18NS --> - <!-- TRANSITIONS --> - <transition> - <id>t1</id> - <x>406</x> - <y>359</y> - <layout> - <offset>0</offset> - </layout> - <label>task</label> - <event type="assign"> - <id>t1_assign</id> - <actions phase="pre"> - <action> - validation("String", new I18nString("I18nString")) + ]]> + </init> + </data> + <transition> + <id>t1</id> + <x>406</x> + <y>359</y> + <title>task + + t1_flex + + + t1_assign + + + - - - - - - + + + + \ No newline at end of file diff --git a/src/test/resources/petriNets/impersonation_test.xml b/src/test/resources/petriNets/impersonation_test.xml deleted file mode 100644 index 7a0d1993284..00000000000 --- a/src/test/resources/petriNets/impersonation_test.xml +++ /dev/null @@ -1,118 +0,0 @@ - - impersonation_test - 1.0.0 - IMP - impersonation_test - home - true - true - false - - test_role - - true - true - - - - test_role - TEST - - - test_role_2 - TEST 2 - - - text_0 - - </data> - <data type="file"> - <id>file_0</id> - <title/> - </data> - <data type="userList" immediate="true"> - <id>user_list</id> - <title/> - </data> - <transition> - <id>t1</id> - <x>580</x> - <y>140</y> - <label/> - <roleRef> - <id>test_role</id> - <logic> - <perform>true</perform> - </logic> - </roleRef> - <dataGroup> - <id>t1_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>text_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>file_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>0</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="assign"> - <id>t1_assign</id> - </event> - <event type="finish"> - <id>t1_finish</id> - </event> - <event type="cancel"> - <id>t1_cancel</id> - </event> - <event type="delegate"> - <id>t1_delegate</id> - </event> - </transition> - <transition> - <id>t2</id> - <x>820</x> - <y>140</y> - <label/> - <roleRef> - <id>test_role_2</id> - <logic> - <perform>true</perform> - </logic> - </roleRef> - </transition> - <transition> - <id>t3</id> - <x>580</x> - <y>300</y> - <label/> - <userRef> - <id>user_list</id> - <logic> - <perform>true</perform> - </logic> - </userRef> - </transition> -</document> \ No newline at end of file diff --git a/src/test/resources/petriNets/importer_upsert.xml b/src/test/resources/petriNets/importer_upsert.xml index 1d3165e3afc..078dbdfb925 100644 --- a/src/test/resources/petriNets/importer_upsert.xml +++ b/src/test/resources/petriNets/importer_upsert.xml @@ -1,13 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>importer_upsert</id> + <version>1.0.0</version> <title>importer_upsert - IMP + + IMP + - 3 + t3 379 273 - + Datagroups - + diff --git a/src/test/resources/petriNets/init_values_test.xml b/src/test/resources/petriNets/init_values_test.xml new file mode 100644 index 00000000000..001be561e8f --- /dev/null +++ b/src/test/resources/petriNets/init_values_test.xml @@ -0,0 +1,198 @@ + + init_values_test + 1.0.0 + Init values test + device_hub + true + true + + boolean_static + + <init>true</init> + </data> + <data type="boolean"> + <id>boolean_dynamic</id> + <title/> + <init dynamic="true">2 == 2</init> + </data> + <data type="button"> + <id>button_static</id> + <title/> + <init>7</init> + </data> + <data type="button"> + <id>button_dynamic</id> + <title/> + <init dynamic="true">5 + 2</init> + </data> + <data type="caseRef"> + <id>caseRef_dynamic</id> + <title/> + <init dynamic="true">[useCase.stringId]</init> + </data> + <data type="date"> + <id>date_static</id> + <title/> + <init>2024-09-30</init> + </data> + <data type="date"> + <id>date_dynamic</id> + <title/> + <init dynamic="true">LocalDate.of(2024,9,30)</init> + </data> + <data type="dateTime"> + <id>dateTime_static</id> + <title/> + <init>2024-09-30T12:00:00.000Z</init> + </data> + <data type="dateTime"> + <id>dateTime_dynamic</id> + <title/> + <init dynamic="true">LocalDateTime.of(2024,9,30,12,0)</init> + </data> + <data type="enumeration"> + <id>enumeration_static</id> + <title/> + <options> + <option>1</option> + <option>2</option> + <option>3</option> + </options> + <init>1</init> + </data> + <data type="enumeration"> + <id>enumeration_dynamic</id> + <title/> + <options> + <init>["1", "2", "3"]</init> + </options> + <init dynamic="true">field.choices.first()</init> + </data> + <data type="enumeration_map"> + <id>enumeration_map_static</id> + <title/> + <options> + <option key="1">1</option> + <option key="2">2</option> + <option key="3">3</option> + </options> + <init>1</init> + </data> + <data type="enumeration_map"> + <id>enumeration_map_dynamic</id> + <title/> + <options> + <init>["1":"1", "2":"2", "3":"3"]</init> + </options> + <init dynamic="true">field.options.keySet().toSorted().first()</init> + </data> + <data type="file"> + <id>file_dynamic</id> + <title/> + <init dynamic="true">FileFieldValue.fromString("pom.xml")</init> + </data> + <data type="fileList"> + <id>fileList_dynamic</id> + <title/> + <init dynamic="true">FileListFieldValue.fromString("pom.xml")</init> + </data> + <data type="filter"> + <id>filter_dynamic</id> + <title/> + <init dynamic="true">findCase{it.id.isNotNull()}.stringId</init> + </data> + <data type="i18n"> + <id>i18n_static</id> + <title/> + <init>I18n</init> + </data> + <data type="i18n"> + <id>i18n_dynamic</id> + <title/> + <init dynamic="true">"I18n"</init> + </data> + <data type="multichoice"> + <id>multichoice_static</id> + <title/> + <options> + <option>1</option> + <option>2</option> + <option>3</option> + </options> + <init>1</init> + </data> + <data type="multichoice"> + <id>multichoice_dynamic</id> + <title/> + <options> + <init>["1", "2", "3"]</init> + </options> + <init dynamic="true">["1"]</init> + </data> + <data type="multichoice_map"> + <id>multichoice_map_static</id> + <title/> + <options> + <option key="1">1</option> + <option key="2">2</option> + <option key="3">3</option> + </options> + <init>1</init> + </data> + <data type="multichoice_map"> + <id>multichoice_map_dynamic</id> + <title/> + <options> + <init>["1":"1", "2":"2", "3":"3"]</init> + </options> + <init dynamic="true">field.options.keySet().toSorted().first()</init> + </data> + <data type="number"> + <id>number_static</id> + <title/> + <init>7</init> + </data> + <data type="number"> + <id>number_dynamic</id> + <title/> + <init dynamic="true">2 + 5</init> + </data> + <data type="stringCollection"> + <id>stringCollection_dynamic</id> + <title/> + <init dynamic="true">["1", "2", "3"]</init> + </data> + <data type="taskRef"> + <id>taskRef_dynamic</id> + <title/> + <init dynamic="true">[useCase.tasks["t0"].taskStringId]</init> + </data> + <data type="text"> + <id>text_static</id> + <title/> + <init>text</init> + </data> + <data type="text"> + <id>text_dynamic</id> + <title/> + <init dynamic="true">"text"</init> + </data> + <data type="user"> + <id>user_dynamic</id> + <title/> + <init dynamic="true">new UserFieldValue(userService.findById(loggedOrSystem.activeActorId).get())</init> + </data> + <data type="userList"> + <id>userList_dynamic</id> + <title/> + <init dynamic="true">new UserListFieldValue(new UserFieldValue(userService.findById(loggedOrSystem.activeActorId).get()))</init> + </data> + + <transition> + <id>t0</id> + <x>0</x> + <y>0</y> + <title>Task ref value + + \ No newline at end of file diff --git a/src/test/resources/petriNets/mortgage.xml b/src/test/resources/petriNets/mortgage.xml new file mode 100644 index 00000000000..9c73a3cd198 --- /dev/null +++ b/src/test/resources/petriNets/mortgage.xml @@ -0,0 +1,1401 @@ + + mortgage + 1.0.0 + Mortgage + true + false + + MTG + + + account_clerk + + true + + + + defaultRole + + true + + + + loan_officer + + true + + + + property_appraiser + + true + + + + author + + true + + + + + + account_clerk + Account clerk + + + loan_officer + Loan officer + + + property_appraiser + Property appraiser + + + system + System + + + account_number + Account number + Please enter your account number - IBAN + + + application_form + Mortgage application form + t24 + + + appraisal + Appraisal report + + + appraised_value + Appraised value + 0 + + + author + Author + + + calc + + <desc>Recalculate the monthly payment</desc> + <event type="set"> + <id>set_event_2</id> + <actions phase="post"> + <action id="action_2"> + <![CDATA[ + change monthly_payment value { return (loan_amount.value+loan.value*0.02*period.value)/(period.value*12);} + ]]> + </action> + </actions> + </event> + </data> + <data type="enumeration"> + <id>city</id> + <title>City + + + confirm + Lien inscription confirmation + Please confirm the lien inscription + + + date_of_birth + Date of Birth + + + delete_instruction + Delete instruction + In order to delete press finish button + + + email + Email + + + first_name + Name + + + income + Monthly Income in EUR + Your average monthly income + + + insurance + Insurance + + + + + + + + Union + + + loan_amount + Loan amount in EUR + + + + + + + 100000 + + set_event_0 + + + + + + + + + monthly_payment + Monthly payment in EUR + 444 + + + period + Repayment period in years + + + + + + + 30 + + set_event_1 + + + + + + + + + postal + Postal code + + set_event_3 + + + + + + + + + sign + Signing instruction + Please sign the mortgage by pressing finish button + + + status + Status + + + street + Street + + + streetnumber + Street Number + + + surname + Surname + + + text_2 + Mortgage approved by loan officer + Please confirm that you approve this mortgage request + + area + + + + text_3 + Mortgage rejected by loan officer + Please confirm that you reject this mortgage request + + area + + + + type + Property + + + + + + + House + + + t10 + 624 + 208 + Appraisal report / Property appraiser + + t10_flex + + + appraised_value + + editable + true + + + + 0 + 0 + 1 + + + + + appraisal + + editable + + + + 0 + 0 + 1 + + + + + property_appraiser + + true + + + + t10_finish + + + = loan_amount.value) { + change status value { return "Mortgage Approved"; } + async.run{ + assignTask("t11") + finishTask("t11") + } + } else { + change status value { return "Mortgage Rejected"; } + async.run{ + assignTask("t15") + finishTask("t15") + } + } + ]]> + + + + + + t11 + 880 + 208 + Approve / System + + t11_flex + + + system + + true + + + + t11_finish + + + + + + + + + t15 + 752 + 336 + Reject / System + + t15_flex + + + system + + true + + + + + t17 + 1136 + 208 + Sign loan contract / Client + + t17_flex + + + account_number + + editable + true + + + + 0 + 0 + 1 + + + + + sign + + visible + + + + 0 + 0 + 1 + + + + + account_clerk + + false + + + + author + + true + + + + loan_officer + + false + + + + property_appraiser + + false + + + + system + + false + + + + t17_finish + + + + + + + + + t19 + 1552 + 208 + Send money / Account clerk + + t19_flex + + + account_number + + visible + + + + 0 + 0 + 1 + + + + + loan_amount + + visible + + + + 0 + 0 + 1 + + + + + account_clerk + + true + + + + t19_finish + + + + + + + + + t2 + 176 + 272 + Apply for mortgage / Client + auto + + t2_flex + + + application_form + + editable + + + + 0 + 0 + 1 + + + + + author + + true + + + + t2_finish + + + + + + + + + t21 + 1328 + 272 + Sign insurance contract / Client + + t21_flex + + + insurance + + editable + true + + + + 0 + 0 + 1 + + + + + account_clerk + + false + + + + author + + true + + + + loan_officer + + false + + + + property_appraiser + + false + + + + system + + false + + + + t21_finish + + + + + + + + + t23 + 1328 + 144 + Confirm lien inscription / Loan officer + + t23_flex + + + confirm + + visible + + + + 0 + 0 + 1 + + + + + account_number + + editable + true + + + + 0 + 0 + 1 + + + + + loan_officer + + true + + + + t23_finish + + + + + + + + + t24 + 176 + 464 + Mortgage application form / System + + t24_flex + + + first_name + + editable + + + + 0 + 0 + 1 + + + + + surname + + editable + + + + 0 + 0 + 1 + + + + + date_of_birth + + editable + + + + 0 + 0 + 1 + + + + + email + + editable + + + + 0 + 0 + 1 + + + + + streetnumber + + editable + + + + 0 + 0 + 1 + + + + + street + + editable + + + + 0 + 0 + 1 + + + + + postal + + editable + + + + 0 + 0 + 1 + + + + + city + + editable + + + + 0 + 0 + 1 + + + + + type + + editable + + + + 0 + 0 + 1 + + + + + income + + editable + + + + 0 + 0 + 1 + + + + + loan_amount + + editable + + + + 0 + 0 + 1 + + + + + period + + editable + + + + 0 + 0 + 1 + + + + + monthly_payment + + visible + + + + 0 + 0 + 1 + + + + + system + + true + + + + + t25 + 48 + 144 + Initialize / System + + + t25_flex + + + author + + true + + + + system + + true + + + + t25_finish + + +// todo: release/8.0.0 + + + + + + + t3 + 400 + 48 + Case info / Loan officer / Property appraiser + + t3_flex + + + application_form + + visible + + + + 0 + 0 + 1 + + + + + appraised_value + + hidden + + + + 0 + 0 + 1 + + + + + loan_officer + + true + + + + property_appraiser + + true + + + + + t4 + 464 + 560 + Status / Client + + t4_flex + + + status + + visible + + + + 0 + 0 + 1 + + + + + application_form + + visible + + + + 0 + 0 + 1 + + + + + account_clerk + + false + + + + author + + true + + + + loan_officer + + false + + + + property_appraiser + + false + + + + system + + false + + + + + t5 + 624 + 464 + Delete / Client + + t5_flex + + + delete_instruction + + visible + + + + 0 + 0 + 1 + + + + + author + + true + + + + t5_finish + + + + + + + + + t7 + 368 + 336 + Reject / Loan officer + + t7_flex + + + text_3 + + visible + + + + 0 + 0 + 1 + + + + + loan_officer + + true + + + + t7_finish + + + + + + + + + t8 + 368 + 208 + Approve / Loan Officer + + t8_flex + + + text_2 + + visible + + + + 0 + 0 + 1 + + + + + loan_officer + + true + + + + t8_finish + + + + + + + + + p10 + 496 + 208 + 0 + + + p11 + 752 + 208 + 0 + + + p12 + 1008 + 208 + 0 + + + p13 + 624 + 336 + 0 + + + p16 + 1200 + 144 + 0 + + + p17 + 1456 + 144 + 0 + + + p18 + 1680 + 208 + 0 + + + p19 + 1200 + 272 + 0 + + + p2 + 48 + 272 + p2 + 0 + + + p20 + 1456 + 272 + 0 + + + p23 + 752 + 560 + 0 + + + p24 + 48 + 48 + p1 + 1 + + + p3 + 304 + 144 + 0 + + + p5 + 368 + 464 + 0 + + + p8 + 304 + 272 + 0 + + + a10 + read + p5 + t4 + 1 + + + a12 + regular + p5 + t5 + 1 + + + a15 + regular + t2 + p8 + 1 + + + a16 + regular + p8 + t7 + 1 + + + a18 + regular + p8 + t8 + 1 + + + a19 + regular + t8 + p10 + 1 + + + a21 + regular + p10 + t10 + 1 + + + a22 + regular + t10 + p11 + 1 + + + a23 + regular + p11 + t11 + 1 + + + a24 + regular + t11 + p12 + 1 + + + a26 + regular + t7 + p13 + 1 + + + a27 + regular + p13 + t5 + 1 + + + a3 + regular + p2 + t2 + 1 + + + a30 + regular + p11 + t15 + 1 + + + a31 + regular + t15 + p13 + 1 + + + a33 + regular + p12 + t17 + 1 + + + a34 + regular + t17 + p16 + 1 + + + a37 + regular + p17 + t19 + 1 + + + a38 + regular + t19 + p18 + 1 + + + a4 + regular + t2 + p3 + 1 + + + a40 + regular + t17 + p19 + 1 + + + a41 + regular + p19 + t21 + 1 + + + a42 + regular + t21 + p20 + 1 + + + a43 + regular + p20 + t19 + 1 + + + a45 + regular + p16 + t23 + 1 + + + a46 + regular + t23 + p17 + 1 + + + a48 + regular + t5 + p23 + 1 + + + a49 + regular + p24 + t25 + 1 + + + a50 + regular + t25 + p2 + 1 + + + a6 + read + p3 + t3 + 1 + + + a8 + regular + t2 + p5 + 1 + + \ No newline at end of file diff --git a/src/test/resources/petriNets/task_authorization_default_test.xml b/src/test/resources/petriNets/task_authorization_default_test.xml new file mode 100644 index 00000000000..baabcfccd1c --- /dev/null +++ b/src/test/resources/petriNets/task_authorization_default_test.xml @@ -0,0 +1,95 @@ + + task_authorization_service_test + 1.0.0 + TaskAuthorizationService test + true + false + + TAT + + + t_assign + 1 + 1 + Test assign + + default + + true + + + + + t_finish + 100 + 1 + Test finish + + default + + true + + + + + t_cancel + 200 + 1 + Test cancel + + default + + true + + + + + t_reassign + 300 + 1 + Test reassign + + default + + true + + + + + t_getdata + 500 + 1 + Test get data + + default + + true + + + + + t_getdata_disabled + 600 + 1 + Test get data of disabled task + + default + + true + + + + + p1 + 600 + 100 + 0 + + + a1 + regular + p1 + t_getdata_disabled + 1 + + \ No newline at end of file diff --git a/src/test/resources/petriNets/task_authorization_test.xml b/src/test/resources/petriNets/task_authorization_test.xml new file mode 100644 index 00000000000..e4aacca2805 --- /dev/null +++ b/src/test/resources/petriNets/task_authorization_test.xml @@ -0,0 +1,222 @@ + + task_authorization_test + 1.0.0 + Task authorization test + false + false + + TAT + + + neg_process_role + neg process role + + + pos_process_role + pos process role + + + neg_getdata_disabled_process_role + neg process role + + + pos_getdata_disabled_process_role + pos process role + + + neg_case_role + + </data> + <data type="userList"> + <id>pos_case_role</id> + <title/> + </data> + <data type="userList"> + <id>neg_getdata_disabled_case_role</id> + <title/> + </data> + <data type="userList"> + <id>pos_getdata_disabled_case_role</id> + <title/> + </data> + <transition> + <id>t_assign</id> + <x>1</x> + <y>1</y> + <title>Test assign + + neg_process_role + + false + + + + pos_process_role + + true + + + + neg_case_role + + false + + + + pos_case_role + + true + + + + + t_finish + 100 + 1 + Test finish + + neg_process_role + + false + + + + pos_process_role + + true + + + + neg_case_role + + false + + + + pos_case_role + + true + + + + + t_cancel + 200 + 1 + Test cancel + + neg_process_role + + false + + + + pos_process_role + + true + + + + neg_case_role + + false + + + + pos_case_role + + true + + + + + t_reassign + 300 + 1 + Test reassign + + neg_process_role + + false + + + + pos_process_role + + true + + + + neg_case_role + + false + + + + pos_case_role + + true + + + + + t_setdata + 400 + 1 + Test set data + + + t_getdata + 500 + 1 + Test get data + + neg_process_role + + false + + + + pos_process_role + + true + + + + neg_case_role + + false + + + + pos_case_role + + true + + + + neg_getdata_disabled_process_role + + false + + + + pos_getdata_disabled_process_role + + true + + + + neg_getdata_disabled_case_role + + false + + + + pos_getdata_disabled_case_role + + true + + + + \ No newline at end of file diff --git a/src/test/resources/petriNets/transaction/transaction_test.xml b/src/test/resources/petriNets/transaction/transaction_test.xml new file mode 100644 index 00000000000..47df0ce19bc --- /dev/null +++ b/src/test/resources/petriNets/transaction/transaction_test.xml @@ -0,0 +1,573 @@ + + transaction_test + 1.0.0 + transaction_test + device_hub + true + true + + TRN + + + + + iterations + + </data> + <data type="button"> + <id>testBasicTransaction</id> + <title/> + <event type="set"> + <id>testBasicTransaction</id> + <actions phase="post"> + <action id="action_0"> + <![CDATA[ + def myTransaction = transaction( + event: { + createCase("transaction_test", "onButton") + change text_without_action value { "xxx" } + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { createCase("transaction_test", "onRollBack") } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testBasicTransactionWithFailure</id> + <title/> + <event type="set"> + <id>testBasicTransactionWithFailure</id> + <actions phase="post"> + <action id="action_1"> + <![CDATA[ + def myTransaction = transaction( + event: { + deleteCase(findCase({it.title.eq("toBeRemoved")})) + createCase("transaction_test", "onButton") + change text_without_action value { "xxx" } + // not runtime exception on purpose + throw new IllegalAccessException("error") + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { createCase("transaction_test", "onRollBack") } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testCreateCaseInTransactionPerformance</id> + <title/> + <event type="set"> + <id>testCreateCaseInTransactionPerformance</id> + <actions phase="post"> + <action id="action_21"> + <![CDATA[ + transaction { + createCase("transaction_test", "transactional create case") + } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testCreateCasePerformance</id> + <title/> + <event type="set"> + <id>testCreateCasePerformance</id> + <actions phase="post"> + <action id="action_22"> + <![CDATA[ + createCase("transaction_test", "non transactional create case") + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testElasticIndexingOnTransactionFailure</id> + <title/> + <event type="set"> + <id>testElasticIndexingOnTransactionFailure</id> + <actions phase="post"> + <action id="action_4"> + <![CDATA[ + def myTransaction = transaction( + event: { + petriNetService.importProcess(new com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams( + new java.io.FileInputStream("src/test/resources/petriNets/transaction/transaction_test_secondary.xml"), + com.netgrif.application.engine.petrinet.domain.VersionType.MAJOR, + userService.getSystemUser().stringId)) + def toBeRemovedCase = createCase("transaction_test_secondary", "toBeRemoved") + assignTask("t1", toBeRemovedCase) + deleteCase(toBeRemovedCase) + createCase("transaction_test", "onButton") + throw new RuntimeException("error") + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { createCase("transaction_test", "onRollBack") } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testElasticIndexingOnTransactionSuccess</id> + <title/> + <event type="set"> + <id>testElasticIndexingOnTransactionSuccess</id> + <actions phase="post"> + <action id="action_5"> + <![CDATA[ + def myTransaction = transaction( + event: { + petriNetService.importProcess(new com.netgrif.application.engine.petrinet.domain.params.ImportProcessParams( + new java.io.FileInputStream("src/test/resources/petriNets/transaction/transaction_test_secondary.xml"), + com.netgrif.application.engine.petrinet.domain.VersionType.MAJOR, + userService.getSystemUser().stringId)) + def toBeRemovedCase = createCase("transaction_test_secondary", "toBeRemoved") + assignTask("t1", toBeRemovedCase) + deleteCase(toBeRemovedCase) + createCase("transaction_test", "onButton") + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { createCase("transaction_test", "onRollBack") } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testFailureInCallBackThrowsError</id> + <title/> + <event type="set"> + <id>testFailureInCallBackThrowsError</id> + <actions phase="post"> + <action id="action_2"> + <![CDATA[ + def myTransaction = transaction( + event: { + createCase("transaction_test", "onButton") + change text_without_action value { "xxx" } + throw new RuntimeException("error") + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { + throw new RuntimeException("error") + createCase("transaction_test", "onRollBack") + } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testNestedDifferentTransactions</id> + <title/> + <event type="set"> + <id>testNestedDifferentTransactions</id> + <actions phase="post"> + <action id="action_10"> + <![CDATA[ + def myTransaction = transaction( + event: { + change testNestedDifferentTransactionsNested value { "some text value" } + createCase("transaction_test", "onButton") + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { createCase("transaction_test", "onRollBack") } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="text"> + <id>testNestedDifferentTransactionsNested</id> + <title/> + <event type="set"> + <id>testNestedDifferentTransactionsNested</id> + <actions phase="post"> + <action id="action_11"> + <![CDATA[ + def myTransaction = transaction( + forceCreation: true, + event: { + createCase("transaction_test", "onButtonNested") + }, + onCommit: { createCase("transaction_test", "onCommitNested") }, + onRollBack: { createCase("transaction_test", "onRollBackNested") } + ) + createCase("transaction_test", "onAlwaysNested") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testNestedDifferentTransactionsWithFailureInNestedTransaction</id> + <title/> + <event type="set"> + <id>testNestedDifferentTransactionsWithFailureInNestedTransaction</id> + <actions phase="post"> + <action id="action_18"> + <![CDATA[ + def myTransaction = transaction( + event: { + change testNestedDifferentTransactionsWithFailureInNestedTransactionNested value { "some text value" } + createCase("transaction_test", "onButton") + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { createCase("transaction_test", "onRollBack") } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="text"> + <id>testNestedDifferentTransactionsWithFailureInNestedTransactionNested</id> + <title/> + <event type="set"> + <id>testNestedDifferentTransactionsWithFailureInNestedTransactionNested</id> + <actions phase="post"> + <action id="action_19"> + <![CDATA[ + def myTransaction = transaction( + forceCreation: true, + event: { + createCase("transaction_test", "onButtonNested") + throw new RuntimeException("error") + }, + onCommit: { createCase("transaction_test", "onCommitNested") }, + onRollBack: { createCase("transaction_test", "onRollBackNested") } + ) + createCase("transaction_test", "onAlwaysNested") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testNestedDifferentTransactionsWithFailureInParentTransaction</id> + <title/> + <event type="set"> + <id>testNestedDifferentTransactionsWithFailureInParentTransaction</id> + <actions phase="post"> + <action id="action_16"> + <![CDATA[ + def myTransaction = transaction( + event: { + change testNestedDifferentTransactionsWithFailureInParentTransactionNested value { "some text value" } + createCase("transaction_test", "onButton") + throw new RuntimeException("error") + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { createCase("transaction_test", "onRollBack") } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="text"> + <id>testNestedDifferentTransactionsWithFailureInParentTransactionNested</id> + <title/> + <event type="set"> + <id>testNestedDifferentTransactionsWithFailureInParentTransactionNested</id> + <actions phase="post"> + <action id="action_17"> + <![CDATA[ + def myTransaction = transaction( + forceCreation: true, + event: { + createCase("transaction_test", "onButtonNested") + }, + onCommit: { createCase("transaction_test", "onCommitNested") }, + onRollBack: { createCase("transaction_test", "onRollBackNested") } + ) + createCase("transaction_test", "onAlwaysNested") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testNestedJoinedTransactions</id> + <title/> + <event type="set"> + <id>testNestedJoinedTransactions</id> + <actions phase="post"> + <action id="action_8"> + <![CDATA[ + def myTransaction = transaction( + event: { + change testNestedJoinedTransactionsNested value { "some text value" } + createCase("transaction_test", "onButton") + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { createCase("transaction_test", "onRollBack") } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="text"> + <id>testNestedJoinedTransactionsNested</id> + <title/> + <event type="set"> + <id>testNestedJoinedTransactionsNested</id> + <actions phase="post"> + <action id="action_9"> + <![CDATA[ + def myTransaction = transaction( + event: { + createCase("transaction_test", "onButtonNested") + }, + onCommit: { createCase("transaction_test", "onCommitNested") }, + onRollBack: { createCase("transaction_test", "onRollBackNested") } + ) + createCase("transaction_test", "onAlwaysNested") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testNestedJoinedTransactionsWithFailureInNestedTransaction</id> + <title/> + <event type="set"> + <id>testNestedJoinedTransactionsWithFailureInNestedTransaction</id> + <actions phase="post"> + <action id="action_14"> + <![CDATA[ + def myTransaction = transaction( + event: { + change testNestedJoinedTransactionsWithFailureInNestedTransactionNested value { "some text value" } + createCase("transaction_test", "onButton") + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { createCase("transaction_test", "onRollBack") } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="text"> + <id>testNestedJoinedTransactionsWithFailureInNestedTransactionNested</id> + <title/> + <event type="set"> + <id>testNestedJoinedTransactionsWithFailureInNestedTransactionNested</id> + <actions phase="post"> + <action id="action_15"> + <![CDATA[ + def myTransaction = transaction( + event: { + createCase("transaction_test", "onButtonNested") + throw new RuntimeException("error") + }, + onCommit: { createCase("transaction_test", "onCommitNested") }, + onRollBack: { createCase("transaction_test", "onRollBackNested") } + ) + createCase("transaction_test", "onAlwaysNested") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testNestedJoinedTransactionsWithFailureInParentTransaction</id> + <title/> + <event type="set"> + <id>testNestedJoinedTransactionsWithFailureInParentTransaction</id> + <actions phase="post"> + <action id="action_12"> + <![CDATA[ + def myTransaction = transaction( + event: { + change testNestedJoinedTransactionsWithFailureInParentTransactionNested value { "some text value" } + createCase("transaction_test", "onButton") + throw new RuntimeException("error") // exception must be thrown after execution of nested action + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { createCase("transaction_test", "onRollBack") } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="text"> + <id>testNestedJoinedTransactionsWithFailureInParentTransactionNested</id> + <title/> + <event type="set"> + <id>testNestedJoinedTransactionsWithFailureInParentTransactionNested</id> + <actions phase="post"> + <action id="action_13"> + <![CDATA[ + def myTransaction = transaction( + event: { + createCase("transaction_test", "onButtonNested") + }, + onCommit: { createCase("transaction_test", "onCommitNested") }, + onRollBack: { createCase("transaction_test", "onRollBackNested") } + ) + createCase("transaction_test", "onAlwaysNested") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testRollBackErrorCurrying</id> + <title/> + <event type="set"> + <id>testRollBackErrorCurrying</id> + <actions phase="post"> + <action id="action_20"> + <![CDATA[ + def myTransaction = transaction( + event: { + createCase("transaction_test", "onButton") + throw new IllegalArgumentException("argument is initialized") + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { e -> + if (e != null && e instanceof IllegalArgumentException) { + createCase("transaction_test", e.getMessage()) + } + } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testTimeout</id> + <title/> + <event type="set"> + <id>testTimeout</id> + <actions phase="post"> + <action id="action_3"> + <![CDATA[ + def myTransaction = transaction( + timeout: 1, // in millis + event: { + createCase("transaction_test", "onButton") + Thread.sleep(50) // make sure it will time-out + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { createCase("transaction_test", "onRollBack") } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="button"> + <id>testTransactionWriteConflict</id> + <title/> + <event type="set"> + <id>testTransactionWriteConflict</id> + <actions phase="post"> + <action id="action_6"> + <![CDATA[ + def myTransaction = transaction( + event: { + change testTransactionWriteConflictNested value { "some text value" } + change text_without_action value { "not nested" } // should be conflicted + }, + onCommit: { createCase("transaction_test", "onCommit") }, + onRollBack: { createCase("transaction_test", "onRollBack") } + ) + createCase("transaction_test", "onAlways") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="text"> + <id>testTransactionWriteConflictNested</id> + <title/> + <event type="set"> + <id>testTransactionWriteConflictNested</id> + <actions phase="post"> + <action id="action_7"> + <![CDATA[ + def myTransaction = transaction( + forceCreation: true, + event: { + change text_without_action value { "nested" } + }, + onCommit: { createCase("transaction_test", "onCommitNested") }, + onRollBack: { createCase("transaction_test", "onRollBackNested") } + ) + createCase("transaction_test", "onAlwaysNested") + change was_transaction_rolled_back value { myTransaction.wasRolledBack } + ]]> + </action> + </actions> + </event> + </data> + <data type="text"> + <id>text_without_action</id> + <title/> + </data> + <data type="boolean"> + <id>was_transaction_rolled_back</id> + <title/> + </data> + <transition> + <id>t1</id> + <x>496</x> + <y>144</y> + <title>t1 + + t1_flex + + + \ No newline at end of file diff --git a/src/test/resources/petriNets/transaction/transaction_test_secondary.xml b/src/test/resources/petriNets/transaction/transaction_test_secondary.xml new file mode 100644 index 00000000000..4ba89f0b676 --- /dev/null +++ b/src/test/resources/petriNets/transaction/transaction_test_secondary.xml @@ -0,0 +1,40 @@ + + transaction_test_secondary + 1.0.0 + transaction_test_secondary + device_hub + true + true + + TRS + + + + + text_2 + + </data> + <data type="text"> + <id>text_without_action</id> + <title/> + </data> + <transition> + <id>t1</id> + <x>496</x> + <y>144</y> + <title>t1 + + t1_flex + + + x1 + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/petriNets/validation/valid_boolean.xml b/src/test/resources/petriNets/validation/valid_boolean.xml index 77c4c1e5054..b2bfe7767c9 100644 --- a/src/test/resources/petriNets/validation/valid_boolean.xml +++ b/src/test/resources/petriNets/validation/valid_boolean.xml @@ -1,17 +1,20 @@ - + valid_boolean - VB1 + 1.0.0 Validacia BooleanFieldu check_circle true true - false + + VB1 + boolean_0 <validations> <validation> - <expression>requiredTrue</expression> + <name>requiredTrue</name> <message>error-boolean</message> </validation> </validations> @@ -20,52 +23,35 @@ <id>t1</id> <x>260</x> <y>100</y> - <label>Test</label> - <dataGroup> - <id>t1_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>boolean_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="assign"> - <id>t1_assign</id> - </event> - <event type="finish"> - <id>t1_finish</id> - </event> - <event type="cancel"> - <id>t1_cancel</id> - </event> - <event type="delegate"> - <id>t1_delegate</id> - </event> + <title>Test + + t1_flex + + + boolean_0 + + editable + + + + 0 + 0 + 1 + + + p1 180 100 1 - false p2 340 100 0 - false a1 @@ -81,4 +67,4 @@ p2 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/validation/valid_date.xml b/src/test/resources/petriNets/validation/valid_date.xml index 008cd3b31bb..29a4d22e28c 100644 --- a/src/test/resources/petriNets/validation/valid_date.xml +++ b/src/test/resources/petriNets/validation/valid_date.xml @@ -1,18 +1,24 @@ - + valid_date - VD1 + 1.0.0 Validacia DateFieldu check_circle true true - false + + VD1 + date01 <validations> <validation> - <expression>between today,future</expression> <!-- od dnes do buducnosti--> + <name>between</name> <!-- od dnes do buducnosti--> + <serverArguments> + <argument>today</argument> + <argument>future</argument> + </serverArguments> <message>error-date01</message> </validation> </validations> @@ -22,7 +28,11 @@ <title/> <validations> <validation> - <expression>between past,today</expression> <!-- od minulosti do dnešného dňa --> + <name>between</name> <!-- od minulosti do dnešného dňa --> + <serverArguments> + <argument>past</argument> + <argument>today</argument> + </serverArguments> <message>error-date02</message> </validation> </validations> @@ -32,7 +42,11 @@ <title/> <validations> <validation> - <expression>between 2020-03-03,today</expression> <!-- od datumu do dnešného dňa --> + <name>between</name> <!-- od datumu do dnešného dňa --> + <serverArguments> + <argument>2020-03-03</argument> + <argument>today</argument> + </serverArguments> <message>error-date03</message> </validation> </validations> @@ -42,7 +56,11 @@ <title/> <validations> <validation> - <expression>between past,2020-03-03</expression> <!-- od minulosti do datumu --> + <name>between</name> <!-- od minulosti do datumu --> + <serverArguments> + <argument>past</argument> + <argument>2020-03-03</argument> + </serverArguments> <message>error-date04</message> </validation> </validations> @@ -52,7 +70,11 @@ <title/> <validations> <validation> - <expression>between 2020-01-01,2022-03-03</expression> <!-- od datumu do datumu --> + <name>between</name> <!-- od datumu do datumu --> + <serverArguments> + <argument>2020-01-01</argument> + <argument>2022-03-03</argument> + </serverArguments> <message>error-date05</message> </validation> </validations> @@ -62,7 +84,7 @@ <title/> <validations> <validation> - <expression>workday</expression> <!-- pracovny den --> + <name>workday</name> <!-- pracovny den --> <message>error-date06</message> </validation> </validations> @@ -72,7 +94,7 @@ <title/> <validations> <validation> - <expression>weekend</expression> <!-- vikend --> + <name>weekend</name> <!-- vikend --> <message>error-date07</message> </validation> </validations> @@ -81,136 +103,113 @@ <id>t1</id> <x>260</x> <y>100</y> - <label>Test</label> - <dataGroup> - <id>t1_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>date01</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>date02</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>date03</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>2</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>date04</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>3</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>date05</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>4</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>date06</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>5</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>date07</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>6</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="assign"> - <id>t1_assign</id> - </event> - <event type="finish"> - <id>t1_finish</id> - </event> - <event type="cancel"> - <id>t1_cancel</id> - </event> - <event type="delegate"> - <id>t1_delegate</id> - </event> + <title>Test + + t1_flex + + + date01 + + editable + + + + 0 + 0 + 1 + + + + + date02 + + editable + + + + 0 + 0 + 1 + + + + + date03 + + editable + + + + 0 + 0 + 1 + + + + + date04 + + editable + + + + 0 + 0 + 1 + + + + + date05 + + editable + + + + 0 + 0 + 1 + + + + + date06 + + editable + + + + 0 + 0 + 1 + + + + + date07 + + editable + + + + 0 + 0 + 1 + + + p1 180 100 1 - false p2 340 100 0 - false a1 @@ -226,4 +225,4 @@ p2 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/validation/valid_number.xml b/src/test/resources/petriNets/validation/valid_number.xml index bbcb7063438..6d221ae1ecc 100644 --- a/src/test/resources/petriNets/validation/valid_number.xml +++ b/src/test/resources/petriNets/validation/valid_number.xml @@ -1,18 +1,20 @@ - + valid_number - VN1 + 1.0.0 Validacia NumberFieldu check_circle true true - false + + VN1 + number01 <validations> <validation> - <expression>odd</expression> + <name>odd</name> <message>error-number01</message> </validation> </validations> @@ -22,7 +24,7 @@ <title/> <validations> <validation> - <expression>even</expression> + <name>even</name> <message>error-number02</message> </validation> </validations> @@ -32,7 +34,7 @@ <title/> <validations> <validation> - <expression>positive</expression> + <name>positive</name> <message>error-number03</message> </validation> </validations> @@ -42,7 +44,7 @@ <title/> <validations> <validation> - <expression>negative</expression> + <name>negative</name> <message>error-number04</message> </validation> </validations> @@ -52,7 +54,7 @@ <title/> <validations> <validation> - <expression>decimal</expression> + <name>decimal</name> <message>error-number05</message> </validation> </validations> @@ -62,7 +64,11 @@ <title/> <validations> <validation> - <expression>inrange 10,20</expression> + <name>inrange</name> + <serverArguments> + <argument>10</argument> + <argument>20</argument> + </serverArguments> <message>error-number06</message> </validation> </validations> @@ -73,11 +79,15 @@ <title/> <validations> <validation> - <expression>odd</expression> + <name>odd</name> <message>error-number07-1</message> </validation> <validation> - <expression>inrange 1,5</expression> + <name>inrange</name> + <serverArguments> + <argument>inf</argument> + <argument>5</argument> + </serverArguments> <message>error-number07-2</message> </validation> </validations> @@ -87,136 +97,113 @@ <id>t1</id> <x>260</x> <y>100</y> - <label>Test</label> - <dataGroup> - <id>t1_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>number01</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>number02</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>number03</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>2</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>number04</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>3</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>number05</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>4</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>number06</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>5</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>number07</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>6</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="assign"> - <id>t1_assign</id> - </event> - <event type="finish"> - <id>t1_finish</id> - </event> - <event type="cancel"> - <id>t1_cancel</id> - </event> - <event type="delegate"> - <id>t1_delegate</id> - </event> + <title>Test + + t1_flex + + + number01 + + editable + + + + 0 + 0 + 1 + + + + + number02 + + editable + + + + 0 + 0 + 1 + + + + + number03 + + editable + + + + 0 + 0 + 1 + + + + + number04 + + editable + + + + 0 + 0 + 1 + + + + + number05 + + editable + + + + 0 + 0 + 1 + + + + + number06 + + editable + + + + 0 + 0 + 1 + + + + + number07 + + editable + + + + 0 + 0 + 1 + + + p1 180 100 1 - false p2 340 100 0 - false a1 @@ -232,4 +219,4 @@ p2 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/validation/valid_regex.xml b/src/test/resources/petriNets/validation/valid_regex.xml index 2b9dd0239a6..6c1b0ee5766 100644 --- a/src/test/resources/petriNets/validation/valid_regex.xml +++ b/src/test/resources/petriNets/validation/valid_regex.xml @@ -1,17 +1,23 @@ - + valid_regex - VR1 + 1.0.0 Validacia regexov check_circle true true - false + + VR1 + regex01 <validations> <validation> - <expression>regex ^([0-9]{1,6})$</expression> <!-- Cislo pocet znakov 1-6 --> + <name>regex</name> + <serverArguments> + <argument>^([0-9]{1,6})$</argument> <!-- Cislo pocet znakov 1-6 --> + </serverArguments> <message>error-regex01</message> </validation> </validations> @@ -21,7 +27,10 @@ <title/> <validations> <validation> - <expression>regex ^([a-zA-Z0-9\-]{10})$</expression> <!-- Cislo alebo pismeno a polcka 10 znakov --> + <name>regex</name> + <serverArguments> + <argument>^([a-zA-Z0-9\-]{10})$</argument> <!-- Cislo alebo pismeno a polcka 10 znakov --> + </serverArguments> <message>error-regex02</message> </validation> </validations> @@ -31,7 +40,10 @@ <title/> <validations> <validation> - <expression>regex ^(TOTOK[a-zA-Z0-9]{7})$</expression> <!-- Prefix max 12 znakov --> + <name>regex</name> + <serverArguments> + <argument>^(TOTOK[a-zA-Z0-9]{7})$</argument> <!-- Prefix max 12 znakov --> + </serverArguments> <message>error-regex03</message> </validation> </validations> @@ -41,7 +53,10 @@ <title/> <validations> <validation> - <expression>regex ^([a-zA-Z0-9 ]{1,10})$</expression> <!-- 10 znakov vratane medzeri --> + <name>regex</name> + <serverArguments> + <argument>^([a-zA-Z0-9 ]{1,10})$</argument> <!-- 10 znakov vratane medzeri --> + </serverArguments> <message>error-regex04</message> </validation> </validations> @@ -51,7 +66,10 @@ <title/> <validations> <validation> - <expression>regex ^([A-ž0-9!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/? ]{1,100})$</expression> <!-- pismena a specialne znaky max100 --> + <name>regex</name> + <serverArguments> + <argument>^([A-ž0-9!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/? ]{1,100})$</argument> <!-- pismena a specialne znaky max100 --> + </serverArguments> <message>error-regex05</message> </validation> </validations> @@ -61,7 +79,10 @@ <title/> <validations> <validation> - <expression>regex ^[a-zA-Z0-9\._\%\+\-]+@[a-zA-Z0-9\.\-]+\.[a-zA-Z]{2,}$</expression> <!-- E-mail --> + <name>regex</name> + <serverArguments> + <argument>^[a-zA-Z0-9\._\%\+\-]+@[a-zA-Z0-9\.\-]+\.[a-zA-Z]{2,}$</argument> <!-- E-mail --> + </serverArguments> <message>error-regex06</message> </validation> </validations> @@ -70,122 +91,100 @@ <id>t1</id> <x>260</x> <y>100</y> - <label>Test</label> - <dataGroup> - <id>t1_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>regex01</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>regex02</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>regex03</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>2</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>regex04</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>3</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>regex05</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>4</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>regex06</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>5</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="assign"> - <id>t1_assign</id> - </event> - <event type="finish"> - <id>t1_finish</id> - </event> - <event type="cancel"> - <id>t1_cancel</id> - </event> - <event type="delegate"> - <id>t1_delegate</id> - </event> + <title>Test + + t1_flex + + + regex01 + + editable + + + + 0 + 0 + 1 + + + + + regex02 + + editable + + + + 0 + 0 + 1 + + + + + regex03 + + editable + + + + 0 + 0 + 1 + + + + + regex04 + + editable + + + + 0 + 0 + 1 + + + + + regex05 + + editable + + + + 0 + 0 + 1 + + + + + regex06 + + editable + + + + 0 + 0 + 1 + + + p1 180 100 1 - false p2 340 100 0 - false a1 @@ -201,4 +200,4 @@ p2 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/petriNets/validation/valid_text.xml b/src/test/resources/petriNets/validation/valid_text.xml index 6935722ddc2..463a8bb1965 100644 --- a/src/test/resources/petriNets/validation/valid_text.xml +++ b/src/test/resources/petriNets/validation/valid_text.xml @@ -1,18 +1,20 @@ - + valid_text - VT1 + 1.0.0 Validacia TextFieldu check_circle true true - false + + VT1 + text01 <validations> <validation> - <expression>email</expression> + <name>email</name> <message>error-text01</message> </validation> </validations> @@ -22,7 +24,7 @@ <title/> <validations> <validation> - <expression>telnumber</expression> + <name>telnumber</name> <message>error-text02</message> </validation> </validations> @@ -32,7 +34,10 @@ <title/> <validations> <validation> - <expression>maxlength 6</expression> + <name>maxlength</name> + <serverArguments> + <argument>6</argument> + </serverArguments> <message>error-text03</message> </validation> </validations> @@ -42,7 +47,10 @@ <title/> <validations> <validation> - <expression>minlength 3</expression> + <name>minlength</name> + <serverArguments> + <argument>3</argument> + </serverArguments> <message>error-text04</message> </validation> </validations> @@ -52,121 +60,150 @@ <title/> <validations> <validation> - <expression>minlength 3</expression> + <name>minlength</name> + <serverArguments> + <argument>3</argument> + </serverArguments> <message>error-text05</message> </validation> <validation> - <expression>maxlength 6</expression> + <name>maxlength</name> + <serverArguments> + <argument>6</argument> + </serverArguments> <message>error-text05</message> </validation> </validations> </data> + <data type="text"> + <id>text06</id> + <title/> + <validations> + <validation> + <name>aaaa</name> + <serverArguments> + <argument dynamic="true">number01.rawValue</argument> + </serverArguments> + <message>error-text06</message> + </validation> + </validations> + </data> + <data type="text"> + <id>text07</id> + <title/> + <validations> + <validation> + <name>number01</name> + <serverArguments> + <argument dynamic="true">number01.rawValue</argument> + </serverArguments> + <message>error-text07</message> + </validation> + </validations> + </data> + <data type="number"> + <id>number01</id> + <title/> + <init>5</init> + </data> <transition> <id>t1</id> <x>260</x> <y>100</y> - <label>Test</label> - <dataGroup> - <id>t1_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>text01</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>text02</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>text03</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>2</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>text04</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>3</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>text05</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>4</y> - <rows>1</rows> - <cols>4</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - </dataGroup> - <event type="assign"> - <id>t1_assign</id> - </event> - <event type="finish"> - <id>t1_finish</id> - </event> - <event type="cancel"> - <id>t1_cancel</id> - </event> - <event type="delegate"> - <id>t1_delegate</id> - </event> + <title>Test + + t1_flex + + + text01 + + editable + + + + 0 + 0 + 1 + + + + + text02 + + editable + + + + 0 + 0 + 1 + + + + + text03 + + editable + + + + 0 + 0 + 1 + + + + + text04 + + editable + + + + 0 + 0 + 1 + + + + + text05 + + editable + + + + 0 + 0 + 1 + + + + + text06 + + editable + + + + 0 + 0 + 1 + + + p1 180 100 1 - false p2 340 100 0 - false a1 @@ -182,4 +219,4 @@ p2 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_combined.xml b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_combined.xml index 3165ab2c233..1ca4a87396d 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_combined.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_combined.xml @@ -1,57 +1,51 @@ - - + permissions_test_anonymous_6 - PTA + 1.0.0 Permissions test anonymous 6 + false true - - - - netRole - Net role - - + + PTA + anonymous - - true + true - + true + netRole - - false + false - + false + - - - - + + netRole + Net role + t1 608 296 - - 0 - - + <roleRef> <id>anonymous</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> + <reassign>true</reassign> + </permission> </roleRef> <roleRef> <id>netRole</id> - <logic> + <permission> <view>false</view> - <delegate>false</delegate> - </logic> + <reassign>false</reassign> + </permission> </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_custom.xml b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_custom.xml index d464a3d94ba..831f48b5eef 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_custom.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_custom.xml @@ -1,39 +1,33 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_anonymous_4</id> - <initials>PTA</initials> + <version>1.0.0</version> <title>Permissions test anonymous 4 + false true - - - + + PTA + anonymous - - true + true - + true + - - - - t1 608 296 - - 0 - - + <roleRef> <id>anonymous</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> + <reassign>true</reassign> + </permission> </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_defined.xml b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_defined.xml index b9451d5e148..2c6e1bc7547 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_defined.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_defined.xml @@ -1,25 +1,19 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_anonymous_2</id> - <initials>PTA</initials> + <version>1.0.0</version> <title>Permissions test anonymous 2 + false true - - - - - - - + + PTA + t1 608 296 - - 0 - - + + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_disabled.xml b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_disabled.xml index becf2e971a4..a9ef769bc0f 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_disabled.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_disabled.xml @@ -1,38 +1,33 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_anonymous_10</id> - <initials>PTA</initials> + <version>1.0.0</version> <title>Permissions test anonymous 10 - - - + false + false + + PTA + anonymous - - true + true - + true + - - - - t1 608 296 - - 0 - - + <roleRef> <id>anonymous</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> + <reassign>true</reassign> + </permission> </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_missing.xml b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_missing.xml index ca1bb624926..22a021c3488 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_missing.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_missing.xml @@ -1,31 +1,26 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_anonymous_7</id> - <initials>PTA</initials> + <version>1.0.0</version> <title>Permissions test anonymous 7 - - - - - - - + false + false + + PTA + t1 608 296 - - 0 - - + <roleRef> <id>anonymous</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> + <reassign>true</reassign> + </permission> </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_negative.xml b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_negative.xml index 00afb2c5939..4c06a5364a6 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_negative.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_negative.xml @@ -1,39 +1,33 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_anonymous_5</id> - <initials>PTA</initials> + <version>1.0.0</version> <title>Permissions test anonymous 5 + false true - - - + + PTA + anonymous - - false + false - + false + - - - - t1 608 296 - - 0 - - + <roleRef> <id>anonymous</id> - <logic> + <permission> <view>false</view> - <delegate>false</delegate> - </logic> + <reassign>false</reassign> + </permission> </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_reserved.xml b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_reserved.xml index cea6fafa266..e2ba9d2fb05 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_reserved.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_reserved.xml @@ -1,28 +1,23 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_anonymous_8</id> - <initials>PTA</initials> + <version>1.0.0</version> <title>Permissions test anonymous 8 - - + false + false + + PTA + anonymous Net role - - - - - t1 608 296 - - 0 - - + + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_shadowed.xml b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_shadowed.xml index 4f9bd8cf4cd..57fb954d70b 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_shadowed.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_shadowed.xml @@ -1,43 +1,37 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_anonymous_3</id> - <initials>PTA</initials> + <version>1.0.0</version> <title>Permissions test anonymous 3 + false true - - - - netRole - Net role - - + + PTA + netRole - - true + true - + true + - - - - + + netRole + Net role + t1 608 296 - - 0 - - + <roleRef> <id>netRole</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> + <reassign>true</reassign> + </permission> </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_shadowed_userref.xml b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_shadowed_userref.xml index 1e69657be3f..5c60747d92b 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_shadowed_userref.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_shadowed_userref.xml @@ -1,43 +1,37 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_anonymous_9</id> - <initials>PTA</initials> + <version>1.0.0</version> <title>Permissions test anonymous 9 + false true - - - - - + + PTA + + userList - - true + true - - - + true + + userList - + </data> - <!-- I18NS --> - <!-- TRANSITIONS --> <transition> <id>t1</id> <x>608</x> <y>296</y> - <layout> - <offset>0</offset> - </layout> - <label></label> - <userRef> + <title/> + <roleRef> <id>userList</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> - </userRef> + <reassign>true</reassign> + </permission> + </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_shadowed_usersref.xml b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_shadowed_usersref.xml index cdc455d6da7..244217613dc 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_shadowed_usersref.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_anonymous_role_shadowed_usersref.xml @@ -1,43 +1,37 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_anonymous_11</id> - <initials>PTA</initials> + <version>1.0.0</version> <title>Permissions test anonymous 11 + false true - - - - - + + PTA + + userList - - true + true - - - + true + + userList - + </data> - <!-- I18NS --> - <!-- TRANSITIONS --> <transition> <id>t1</id> <x>608</x> <y>296</y> - <layout> - <offset>0</offset> - </layout> - <label></label> - <usersRef> + <title/> + <roleRef> <id>userList</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> - </usersRef> + <reassign>true</reassign> + </permission> + </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_combined_roles_defined.xml b/src/test/resources/predefinedPermissions/role_permissions_combined_roles_defined.xml index bc74887e06b..bb579a34b22 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_combined_roles_defined.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_combined_roles_defined.xml @@ -1,26 +1,19 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_combined_2</id> - <initials>PTC</initials> + <version>1.0.0</version> <title>Permissions test combined 2 true true - - - - - - - + + PTC + t1 608 296 - - 0 - - + + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_combined_roles_undefined.xml b/src/test/resources/predefinedPermissions/role_permissions_combined_roles_undefined.xml index 446834a9273..e0f51509a2d 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_combined_roles_undefined.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_combined_roles_undefined.xml @@ -1,24 +1,19 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_combined_1</id> - <initials>PTC</initials> + <version>1.0.0</version> <title>Permissions test combined 1 - - - - - - - + false + false + + PTC + t1 608 296 - - 0 - - + + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_default_role_combined.xml b/src/test/resources/predefinedPermissions/role_permissions_default_role_combined.xml index 061a9adcbab..c31a6796380 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_default_role_combined.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_default_role_combined.xml @@ -1,57 +1,44 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_default_6</id> - <initials>PTD</initials> + <version>1.0.0</version> <title>Permissions test default 6 true - - - - netRole - Net role - - - - default - - true - true - - + false + + PTD + netRole - - false + false - + false + - - - - + + netRole + Net role + t1 608 296 - - 0 - - + <roleRef> <id>default</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> + <reassign>true</reassign> + </permission> </roleRef> <roleRef> <id>netRole</id> - <logic> + <permission> <view>false</view> - <delegate>false</delegate> - </logic> + <reassign>false</reassign> + </permission> </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_default_role_custom.xml b/src/test/resources/predefinedPermissions/role_permissions_default_role_custom.xml index a8820f38b4b..f0ff11d4908 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_default_role_custom.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_default_role_custom.xml @@ -1,39 +1,26 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_default_4</id> - <initials>PTD</initials> + <version>1.0.0</version> <title>Permissions test default 4 true - - - - - default - - true - true - - - - - - + false + + PTD + t1 608 296 - - 0 - - + <roleRef> <id>default</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> + <reassign>true</reassign> + </permission> </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_default_role_defined.xml b/src/test/resources/predefinedPermissions/role_permissions_default_role_defined.xml index 9e877ec7a84..16ee2d241e7 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_default_role_defined.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_default_role_defined.xml @@ -1,25 +1,19 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_default_2</id> - <initials>PTD</initials> + <version>1.0.0</version> <title>Permissions test default 2 true - - - - - - - + false + + PTD + t1 608 296 - - 0 - - + + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_default_role_disabled.xml b/src/test/resources/predefinedPermissions/role_permissions_default_role_disabled.xml index 490145a3fd5..f7b661619f3 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_default_role_disabled.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_default_role_disabled.xml @@ -1,38 +1,26 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_default_10</id> - <initials>PTD</initials> + <version>1.0.0</version> <title>Permissions test default 10 - - - - - default - - true - true - - - - - - + false + false + + PTD + t1 608 296 - - 0 - - + <roleRef> <id>default</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> + <reassign>true</reassign> + </permission> </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_default_role_missing.xml b/src/test/resources/predefinedPermissions/role_permissions_default_role_missing.xml index c66effbf3d3..0ffac5cc3a1 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_default_role_missing.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_default_role_missing.xml @@ -1,31 +1,26 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_default_7</id> - <initials>PTD</initials> + <version>1.0.0</version> <title>Permissions test default 7 - - - - - - - + false + false + + PTD + t1 608 296 - - 0 - - + <roleRef> <id>default</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> + <reassign>true</reassign> + </permission> </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_default_role_negative.xml b/src/test/resources/predefinedPermissions/role_permissions_default_role_negative.xml index c7574cd6417..216daacd311 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_default_role_negative.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_default_role_negative.xml @@ -1,39 +1,26 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_default_5</id> - <initials>PTD</initials> + <version>1.0.0</version> <title>Permissions test default 5 true - - - - - default - - false - false - - - - - - + false + + PTD + t1 608 296 - - 0 - - + <roleRef> <id>default</id> - <logic> + <permission> <view>false</view> - <delegate>false</delegate> - </logic> + <reassign>false</reassign> + </permission> </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_default_role_reserved.xml b/src/test/resources/predefinedPermissions/role_permissions_default_role_reserved.xml index 5756c8d623c..3842c0014e5 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_default_role_reserved.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_default_role_reserved.xml @@ -1,28 +1,23 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_default_8</id> - <initials>PTD</initials> + <version>1.0.0</version> <title>Permissions test default 8 - - + false + false + + PTD + default Net role - - - - - t1 608 296 - - 0 - - + + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_default_role_shadowed.xml b/src/test/resources/predefinedPermissions/role_permissions_default_role_shadowed.xml index 9c3437a0526..0b8399ff321 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_default_role_shadowed.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_default_role_shadowed.xml @@ -1,43 +1,37 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_default_3</id> - <initials>PTD</initials> + <version>1.0.0</version> <title>Permissions test default 3 true - - - - netRole - Net role - - + false + + PTD + netRole - - true + true - + true + - - - - + + netRole + Net role + t1 608 296 - - 0 - - + <roleRef> <id>netRole</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> + <reassign>true</reassign> + </permission> </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_default_role_shadowed_userref.xml b/src/test/resources/predefinedPermissions/role_permissions_default_role_shadowed_userref.xml index 131a28f2806..e2dc1daa80a 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_default_role_shadowed_userref.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_default_role_shadowed_userref.xml @@ -1,43 +1,37 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_default_9</id> - <initials>PTD</initials> + <version>1.0.0</version> <title>Permissions test default 9 true - - - - - + false + + PTD + + userList - - true + true - - - + true + + userList - + </data> - <!-- I18NS --> - <!-- TRANSITIONS --> <transition> <id>t1</id> <x>608</x> <y>296</y> - <layout> - <offset>0</offset> - </layout> - <label></label> - <userRef> + <title/> + <roleRef> <id>userList</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> - </userRef> + <reassign>true</reassign> + </permission> + </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/predefinedPermissions/role_permissions_default_role_shadowed_usersref.xml b/src/test/resources/predefinedPermissions/role_permissions_default_role_shadowed_usersref.xml index 3b2a7359c9c..fec914a6819 100644 --- a/src/test/resources/predefinedPermissions/role_permissions_default_role_shadowed_usersref.xml +++ b/src/test/resources/predefinedPermissions/role_permissions_default_role_shadowed_usersref.xml @@ -1,43 +1,37 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../main/resources/petriNets/petriflow_schema.xsd"> <id>permissions_test_default_11</id> - <initials>PTD</initials> + <version>1.0.0</version> <title>Permissions test default 11 true - - - - - + false + + PTD + + userList - - true + true - - - + true + + userList - + </data> - <!-- I18NS --> - <!-- TRANSITIONS --> <transition> <id>t1</id> <x>608</x> <y>296</y> - <layout> - <offset>0</offset> - </layout> - <label></label> - <usersRef> + <title/> + <roleRef> <id>userList</id> - <logic> + <permission> <view>true</view> - <delegate>true</delegate> - </logic> - </usersRef> + <reassign>true</reassign> + </permission> + </roleRef> + <flex> + <id>t1_flex</id> + </flex> </transition> - <!-- PLACES --> - <!-- ARCS --> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/prikladFM_test.xml b/src/test/resources/prikladFM_test.xml index 369a2e491b8..18c658c0776 100644 --- a/src/test/resources/prikladFM_test.xml +++ b/src/test/resources/prikladFM_test.xml @@ -1,1211 +1,1320 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- version 1.0.0 --> -<document> - <id>prikladFM_test.xml</id> - <initials>TST</initials> +<process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../main/resources/petriNets/petriflow_schema.xsd"> + <id>prikladFM_test</id> + <version>1.0.0</version> <title>Test false + false + + TST + + + role1 + client + + + role2 + fm servis + + + role3 + client manager + - 1 + data1 Poradové číslo - 2 - Lehota uloženia - - - 3 - Lokalizácia - - - 4 - Od (dátum) - - - 5 - Do (dátum) - - - 6 - Krajina pôvodu - Slovensko - Česká Republika - Rakúsko - - - 7 - Ukl. jednotka - - - 8 - Miestnosť - - - 9 - Odovzdávajúci - 1 - 2 - - - 10 + data10 Forma - 11 + data11 Vecný obsah UJ - 12 + data12 Čiarový kód - 13 + data13 Registratúrna značka - 14 + data14 Pododdelenie - 15 + data15 Odovzdávajúci útvar - 16 + data16 Plomba - 17 + data17 Dátum udalosti - 18 + data18 Znak hodnoty - 19 + data19 Oddelenie + + data2 + Lehota uloženia + - 20 + data20 Dátum odovzdania - 21 + data21 Typ spisu - 22 + data22 Vypožičané dňa - 23 + data23 Vybral - 25 + data25 Oddelenie - 27 + data27 Ukl. jednotka - 28 + data28 Vrátiť do - 29 + data29 Multiple choice - A - B - C + + + + + + + + data3 + Lokalizácia + + + data4 + Od (dátum) + + + data5 + Do (dátum) + + + data6 + Krajina pôvodu + + + + + + + + data7 + Ukl. jednotka + + + data8 + Miestnosť + + + data9 + Odovzdávajúci + + + + - - 1 - client - - - 2 - fm servis - - - 3 - client manager - - - 0 - 100 - 260 - - 5 - false - - - 8 - 260 - 180 - - 0 - false - - - 14 - 260 - 60 - - 0 - false - - - 22 - 540 - 180 - - 0 - false - - - 29 - 580 - 260 - - 0 - false - - - 34 - 700 - 180 - - 0 - false - - - 38 - 860 - 180 - - 0 - false - - - 44 - 860 - 60 - - 0 - false - - - 49 - 1060 - 180 - - 0 - false - - - 53 - 1060 - 340 - - 0 - false - - - 64 - 1500 - 180 - - 1 - false - - - 69 - 1260 - 340 - - 0 - false - - - 70 - 1420 - 340 - - 0 - false - - - 75 - 1500 - 260 - - 0 - false - - - 124 - 1300 - 100 - - 0 - false - - - 237 - 420 - 60 - - 0 - false - - - 240 - 380 - 340 - - 0 - false - - 1 + t1 180 180 - + Zaevidovanie UJ - 1 - + role1 + true - + - 3 - - true - + role3 + + true + - - 29 - - true - - - - 1 - - true - true - - - - 2 - - true - true - - - - 3 - - true - - - - 4 - - true - - - - 5 - - false - 10y - - - - 6 - - true - - - - 7 - - true - - - - 8 - - true - - - - 9 - - true - - - - 10 - - true - - - - 11 - - true - - - - 12 - - true - - - - 13 - - true - - - - 14 - - true - - - - 15 - - true - - - - 16 - - true - - - - 17 - - true - - - - 18 - - true - - - - 19 - - true - - - - 20 - - true - - - - 21 - - true - - + + t1_flex + + + data29 + + editable + + + + + + data1 + + editable + + + + + + data2 + + editable + + + + + + data3 + + editable + + + + + + data4 + + editable + + + + + + data5 + + editable + + + + + + data6 + + editable + + + + + + data7 + + editable + + + + + + data8 + + editable + + + + + + data9 + + editable + + + + + + data10 + + editable + + + + + + data11 + + editable + + + + + + data12 + + editable + + + + + + data13 + + editable + + + + + + data14 + + editable + + + + + + data15 + + editable + + + + + + data16 + + editable + + + + + + data17 + + editable + + + + + + data18 + + editable + + + + + + data19 + + editable + + + + + + data20 + + editable + + + + + + data21 + + editable + + + + - 2 - 180 - 340 - + t10 + 380 + 180 + Návrh miesta a termínu odovzdania - 1 - + role1 + true - + - 10 - 380 - 180 - + t122 + 1180 + 100 + Požiadavka na scan UJ - 1 - + role1 + true - + - 13 + t125 + 1420 + 100 + Zaslanie scanu UJ + + role2 + + true + + + + + t13 340 60 - + Vrátenie UJ + + role1 + + true + + + + + t181 + 660 + 460 + Data UJ - 1 - + role2 + true - + + + t181_flex + + + data1 + + editable + + + + + + data2 + + editable + + + + + + data3 + + editable + + + + + + data4 + + editable + + + + + + data5 + + editable + + + + + + data6 + + editable + + + + + + data7 + + editable + + + + + + data8 + + editable + + + + + + data9 + + editable + + + + + + data10 + + editable + + + + + + data11 + + editable + + + + + + data12 + + editable + + + + + + data13 + + editable + + + + + + data14 + + editable + + + + + + data15 + + editable + + + + + + data16 + + editable + + + + + + data17 + + editable + + + + + + data18 + + editable + + + + + + data19 + + editable + + + + + + data20 + + editable + + + + + + data21 + + editable + + + + + + data22 + + editable + + + + + + data23 + + editable + + + + + + data25 + + editable + + + + + + data27 + + editable + + + + + + data28 + + editable + + + + + + data29 + + editable + + + + - 19 + t19 180 60 - + Vypožičanie UJ - 1 - + role1 + true - + - - 22 - - true - - - - 23 - - true - - - - 13 - - true - - - - 19 - - true - - - - 3 - - true - - - - 7 - - true - - - - 28 - - true - - + + t19_flex + + + data22 + + editable + + + + + + data23 + + editable + + + + + + data13 + + editable + + + + + + data19 + + editable + + + + + + data3 + + editable + + + + + + data7 + + editable + + + + + + data28 + + editable + + + + - 23 + t2 + 180 + 340 + Odovzdanie UJ do RS-FMS + + role1 + + true + + + + + t23 620 180 - + Potvrdenie terminu + + role2 + + true + + + + + t242 + 940 + 180 + Prve zaevidovanie UJ - 2 - + role2 + true - + - 26 + t26 700 260 - + Upresnenie miesta a termínu odovzdania - 2 - + role2 + true - + - 31 + t31 420 260 - + Upresnenie miesta a termínu odovzdania - 1 - + role1 + true - + - 36 + t36 780 180 - + Odovzdanie - 1 - + role1 + true - + - 39 + t39 1060 100 - + Zaevidovanie UJ - 2 - + role2 + true - + - 42 + t42 940 100 - + Riešenie spornej veci - 2 - + role2 + true - + - 45 + t45 780 100 - + Riešenie spornej veci - 1 - + role1 + true - + - 51 + t51 1060 260 - + Požiadavka na vypožičanie - 1 - + role1 + true - + - 52 + t52 1180 340 - + Odovzdanie vypožičanej UJ - 2 - + role2 + true - + - 54 + t54 1420 180 - + Skartácia - 2 - + role2 + true - + - 66 + t66 1340 340 - + Prebratie požičanej UJ - 1 - + role1 + true - + - 67 + t67 1500 340 - + Vrátenie požičanej UJ - 1 - + role1 + true - + - 68 + t68 1420 260 - + Založenie vrátenej UJ - 2 - + role2 + true - + - - 122 - 1180 + + p0 + 100 + 260 + A + 5 + + + p124 + 1300 100 - - - 1 - - true - - - - - 125 + P + 0 + + + p14 + 260 + 60 + C + 0 + + + p22 + 540 + 180 + E + 0 + + + p237 + 420 + 60 + D + 0 + + + p240 + 380 + 340 + K + 0 + + + p29 + 580 + 260 + F + 0 + + + p34 + 700 + 180 + G + 0 + + + p38 + 860 + 180 + H + 0 + + + p44 + 860 + 60 + I + 0 + + + p49 + 1060 + 180 + J + 0 + + + p53 + 1060 + 340 + L + 0 + + + p64 + 1500 + 180 + Q + 1 + + + p69 + 1260 + 340 + M + 0 + + + p70 1420 - 100 - - - 2 - - true - - - - - 181 - 660 - 460 - - - 2 - - true - - - - 1 - - true - - - - 2 - - true - - - - 3 - - true - - - - 4 - - true - - - - 5 - - true - - - - 6 - - true - - - - 7 - - true - - - - 8 - - true - - - - 9 - - true - - - - 10 - - true - - - - 11 - - true - - - - 12 - - true - - - - 13 - - true - - - - 14 - - true - - - - 15 - - true - - - - 16 - - true - - - - 17 - - true - - - - 18 - - true - - - - 19 - - true - - - - 20 - - true - - - - 21 - - true - - - - 22 - - true - - - - 23 - - true - - - - 25 - - true - - - - 27 - - true - - - - 28 - - true - - - - 29 - - true - - - - - 242 - 940 + 340 + N + 0 + + + p75 + 1500 + 260 + O + 0 + + + p8 + 260 180 - - - 2 - - true - - - + B + 0 + - 4 + a11 regular - 0 - 1 + p8 + t10 1 - 5 + a121 regular - 0 - 2 + t2 + p22 1 - 9 + a123 regular - 1 - 8 + p49 + t122 1 - 11 + a126 regular - 8 - 10 + t122 + p124 1 - 17 + a127 regular - 14 - 13 + p124 + t125 1 - 18 + a128 regular - 13 - 8 + t125 + p49 1 - 20 + a17 regular - 8 - 19 + p14 + t13 1 - 21 + a18 regular - 19 - 14 + t13 + p8 1 - 24 + a20 regular - 10 - 22 + p8 + t19 1 - 25 + a21 regular - 22 - 23 + t19 + p14 1 - 27 + a238 regular - 22 - 26 + t10 + p237 1 - 30 + a239 regular - 26 - 29 + p237 + t39 1 + + 860 + 20 + - 32 + a24 regular - 29 - 31 + t10 + p22 1 - 33 + a241 regular - 31 - 22 + t2 + p240 1 - 35 + a243 regular - 23 - 34 + p240 + t242 1 + + 940 + 340 + - 37 + a244 regular - 34 - 36 + p38 + t242 1 - 40 + a245 regular - 36 - 38 + t242 + p49 1 - 41 + a25 regular - 38 - 39 + p22 + t23 1 - 43 + a27 regular - 38 - 42 + p22 + t26 1 - 46 + a30 regular - 42 - 44 + t26 + p29 1 - 47 + a32 regular - 44 - 45 + p29 + t31 1 - 48 + a33 regular - 45 - 38 + t31 + p22 1 - 50 + a35 regular - 39 - 49 + t23 + p34 1 - 57 + a37 regular - 49 - 51 + p34 + t36 1 - 58 + a4 regular - 51 - 53 + p0 + t1 1 - 59 + a40 regular - 53 - 52 + t36 + p38 1 - 61 + a41 regular - 49 - 54 + p38 + t39 1 - 65 + a43 regular - 54 - 64 + p38 + t42 1 - 71 + a46 regular - 52 - 69 + t42 + p44 1 - 72 + a47 regular - 69 - 66 + p44 + t45 1 - 73 + a48 regular - 66 - 70 + t45 + p38 1 - 74 + a5 regular - 70 - 67 + p0 + t2 1 - 76 + a50 regular - 67 - 75 + t39 + p49 1 - 77 + a57 regular - 75 - 68 + p49 + t51 1 - 78 + a58 regular - 68 - 49 + t51 + p53 1 - 121 + a59 regular - 2 - 22 + p53 + t52 1 - 123 + a61 regular - 49 - 122 + p49 + t54 1 - 126 + a65 regular - 122 - 124 + t54 + p64 1 - 127 + a71 regular - 124 - 125 + t52 + p69 1 - 128 + a72 regular - 125 - 49 + p69 + t66 1 - 238 + a73 regular - 10 - 237 + t66 + p70 1 - 239 + a74 regular - 237 - 39 + p70 + t67 1 - - 860 - 20 - - 241 + a76 regular - 2 - 240 + t67 + p75 1 - 243 + a77 regular - 240 - 242 + p75 + t68 1 - - 940 - 340 - - 244 + a78 regular - 38 - 242 + t68 + p49 1 - 245 + a9 regular - 242 - 49 + t1 + p8 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/priority_test.xml b/src/test/resources/priority_test.xml index 816f8ba57b4..f2593bcd7e7 100644 --- a/src/test/resources/priority_test.xml +++ b/src/test/resources/priority_test.xml @@ -1,86 +1,91 @@ - - + test - TST + 1.0.0 Test false - - 1 - 180 - 220 - - 1 - false - - - 8 - 420 - 220 - - 0 - false - + false + + TST + - 2 + t2 300 140 - - 3 + 3 + + 3 + - 3 + t3 300 220 - - 1 + 1 + + 1 + - 4 + t4 300 300 - - 2 + 2 + + 2 + + + p1 + 180 + 220 + 1 + + + p8 + 420 + 220 + 0 + - 5 + a10 regular - 1 - 2 + t3 + p8 1 - 6 + a11 regular - 1 - 3 + t4 + p8 1 - 7 + a5 regular - 1 - 4 + p1 + t2 1 - 9 + a6 regular - 2 - 8 + p1 + t3 1 - 10 + a7 regular - 3 - 8 + p1 + t4 1 - 11 + a9 regular - 4 - 8 + t2 + p8 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/process_delete_test.xml b/src/test/resources/process_delete_test.xml index b921eef0bec..960a30352ef 100644 --- a/src/test/resources/process_delete_test.xml +++ b/src/test/resources/process_delete_test.xml @@ -1,12 +1,12 @@ - - + processDeleteTest - PDT + 1.0.0 Process Delete Test - false - - + false + false + + PDT + role1 Role 1 @@ -15,21 +15,16 @@ role2 Role 2 - - - - 1 + t1 553 304 - + Task 1 - 2 + t2 653 304 - + Task 2 - - - + \ No newline at end of file diff --git a/src/test/resources/process_search_test.xml b/src/test/resources/process_search_test.xml index f92fedb067b..edba22872fd 100644 --- a/src/test/resources/process_search_test.xml +++ b/src/test/resources/process_search_test.xml @@ -1,16 +1,14 @@ - - + processSearchTest - PST + 1.0.0 Process Search Test + false + false + + PST + test + Process Search Case Name - false - - test - - - role1 Role 1 @@ -19,21 +17,16 @@ role2 Role 2 - - - - 1 + t1 553 304 - + Task 1 - 2 + t2 653 304 - + Task 2 - - - + \ No newline at end of file diff --git a/src/test/resources/read_test.xml b/src/test/resources/read_test.xml index 105c6496e81..890dcaeadad 100644 --- a/src/test/resources/read_test.xml +++ b/src/test/resources/read_test.xml @@ -1,55 +1,55 @@ - - + test - TST + 1.0.0 Test false - + false + + TST + - 1 - Role + r1 + Role + + t3 + 265 + 89 + Test read arc + + r1 + + true + true + + + - 1 + p1 142 79 - + IN 1 - false - 6 + p6 384 78 - + OUT 0 - false - - 3 - 265 - 89 - - - 1 - - true - true - - - - 4 + a4 read - 1 - 3 + p1 + t3 1 - 7 + a7 regular - 3 - 6 + t3 + p6 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/remoteFileField.xml b/src/test/resources/remoteFileField.xml index 41604c0e405..bfb20a73b23 100644 --- a/src/test/resources/remoteFileField.xml +++ b/src/test/resources/remoteFileField.xml @@ -1,27 +1,43 @@ - - + remote_file_field_net - TST + 1.0.0 Test true + false + + TST + + + file Remote File Remote file test-file.txt:https://netgrif.com - + + true + task 0 0 - - - file - - visible - - + Task + + task_flex + + + file + + visible + + + + 0 + 0 + 1 + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/remoteFileListField.xml b/src/test/resources/remoteFileListField.xml index e9000614929..d11864ac757 100644 --- a/src/test/resources/remoteFileListField.xml +++ b/src/test/resources/remoteFileListField.xml @@ -1,27 +1,32 @@ - - + remote_file_field_net - TST + 1.0.0 Test true fileList Remote File List Remote file list - test-file.txt:https://netgrif.com,test-file-list.txt:https://netgrif.com - + FileListFieldValue.fromString("test-file.txt:https://netgrif.com,test-file-list.txt:https://netgrif.com") + + true + task 0 0 - - - fileList - - visible - - + Task + + task_flex + + + fileList + + visible + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/removeRole_test.xml b/src/test/resources/removeRole_test.xml index ebfa71108ee..b75c6037cb2 100644 --- a/src/test/resources/removeRole_test.xml +++ b/src/test/resources/removeRole_test.xml @@ -1,30 +1,36 @@ - - + test - TST + 1.0.0 Test false - + false + + TST + Nová organizácia - + + admin admin - 1 + admin_assign - + + + ]]> + - - 1 + + admin_remove - + + + ]]> + @@ -32,4 +38,4 @@ manager manager - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/request.xml b/src/test/resources/request.xml new file mode 100644 index 00000000000..42c77acf87a --- /dev/null +++ b/src/test/resources/request.xml @@ -0,0 +1,582 @@ + + + request + 1.0.0 + New request + fact_check + true + true + + first + First + + + registration + Registration + + + second + Second + + + system + System + + + identity + Identity + + + request_origin + Origin of the request + + + + + + + customer_id + Customer ID + + + inrange + + 1000 + 2999 + + + + + + form_ref + + <init>t9</init> + </data> + <data type="text"> + <id>name</id> + <title>Name + + + surname + Surname + ` + + + email + Email + + + request_text + Request + + + answer_department + Answer of the department + + + answer_registration + Answer of the registration + + + status + Status + + + t1 + 496 + 208 + Submit request + + identity + + true + + + + t1_0 + + + form_ref + + editable + + + + + + t1_finish + + + + + + + + + t2 + 752 + 208 + Registration + + registration + + true + + + + t2_0 + + + request_origin + + editable + + + list + + + + + + form_ref + + visible + + + + + + t2_finish + + + + + + + + + + + + + + t3 + 976 + 176 + To first + + system + + true + + + + + t4 + 1232 + 176 + First department + + first + + true + + + + t4_0 + + + answer_department + + editable + true + + + textarea + + + + + + form_ref + + visible + + + + + + + t5 + 1456 + 208 + Answer of the registration + + registration + + true + + + + t5_0 + + + answer_registration + + editable + true + + + textarea + + + + + + answer_department + + visible + + + + + + form_ref + + visible + + + + + + t5_finish + + + + + + + + + t6 + 976 + 272 + To second + + system + + true + + + + + t7 + 1232 + 272 + Second department + + second + + true + + + + t7_0 + + + answer_department + + editable + true + + + + + + form_ref + + visible + + + + + + + t8 + 752 + 304 + Detail + + default + + true + + + + t8_0 + + + status + + visible + + + + + + answer_registration + + hidden + + + + + + form_ref + + visible + + + + + + + t9 + 656 + 48 + Form + + system + + true + + + + t9_0 + + + name + + editable + true + + + + + + surname + + editable + true + + + + + + email + + editable + true + + + + + + customer_id + + editable + true + + + + + + request_text + + editable + true + + + textarea + + + + + + + p1 + 368 + 208 + 1 + + + p2 + 624 + 208 + 0 + + + p3 + 848 + 208 + 0 + + + p4 + 1104 + 176 + 0 + + + p5 + 1328 + 208 + 0 + + + p6 + 1584 + 208 + 0 + + + p7 + 1104 + 272 + 0 + + + p9 + 624 + 304 + 0 + + + a1 + regular + p1 + t1 + 1 + + + a10 + regular + t5 + p6 + 1 + + + a12 + regular + p3 + t6 + 1 + + + a13 + regular + t6 + p7 + 1 + + + a14 + regular + p7 + t7 + 1 + + + a15 + regular + t7 + p5 + 1 + + + a17 + regular + t1 + p9 + 1 + + + a19 + read + p9 + t8 + 1 + + + a2 + regular + t1 + p2 + 1 + + + a3 + regular + p2 + t2 + 1 + + + a4 + regular + t2 + p3 + 1 + + + a5 + regular + p3 + t3 + 1 + + + a6 + regular + t3 + p4 + 1 + + + a7 + regular + p4 + t4 + 1 + + + a8 + regular + t4 + p5 + 1 + + + a9 + regular + p5 + t5 + 1 + + \ No newline at end of file diff --git a/src/test/resources/reset_inhibitor_test.xml b/src/test/resources/reset_inhibitor_test.xml index 8bc2fd9a060..a77ff3ef813 100644 --- a/src/test/resources/reset_inhibitor_test.xml +++ b/src/test/resources/reset_inhibitor_test.xml @@ -1,83 +1,86 @@ - - + test - TST + 1.0.0 Test false + false + + TST + + + + + role1 + Agent + - 1 + data1 Poradové číslo - - 1 - Agent - - - 1 - 274 - 203 - - 5 - false - - - 4 - 527 - 197 - - 0 - false - - 2 + t2 411 142 - + reset - 1 - + role1 + true - + - 3 + t3 402 257 - + inhibit - 1 - + role1 + true - + + + p1 + 274 + 203 + start + 5 + + + p4 + 527 + 197 + end + 0 + - 5 + a5 inhibitor - 1 - 3 + p1 + t3 1 - 6 + a6 reset - 1 - 2 + p1 + t2 1 - 7 + a7 regular - 2 - 4 + t2 + p4 1 - 8 + a8 regular - 3 - 4 + t3 + p4 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/role_all_data.xml b/src/test/resources/role_all_data.xml index 37989c7f301..e7d696f53ff 100644 --- a/src/test/resources/role_all_data.xml +++ b/src/test/resources/role_all_data.xml @@ -1,104 +1,84 @@ - - - all_data - ALL + + all_data + 1.0.0 All Data device_hub true true - false + + ALL + All data test default case name - - - admin - Create Role - - admin - + admin_role + true true - + - - - number - Number - 10000 - - - number_currency - Number currency - 10000 - - - EUR - 2 - sk_SK - - - - - - text - Text - Lorem ipsum + + admin_role + Create Role + + + boolean + Boolean + True - - password_data - Password from data + + button + Button + Push - password + fab - - password_dataref - Password from dataRef + + date + Date + 2019-01-01 - - text_area - Text area - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vitae magna in libero semper - vulputate ut eu sapien. Phasellus vel. - - - htmltextarea - red - 12 - + + datetime + Datetime + 2019-01-01T20:00:00.000Z - enumeration Enumeration - Alice - Bob - Carol + + + + + Bob enumeration_autocomplete Enumeration autocomplete - Alice - Bob - Carol + + + + + Bob - autocomplete + autocomplete enumeration_list Enumeration list - Alice - Bob - Carol + + + + + Bob - list + list - enumeration_map Enumeration Map @@ -109,31 +89,48 @@ bo - + + file + File + + file_set + + + + + + + + + fileList + File List + multichoice Multichoice - Alice - Bob - Carol - - Alice - Bob - + + + + + - multichoice_list Multichoice list - Alice - Bob - Carol + + + + + Alice,Bob - list + list - multichoice_map Multichoice Map @@ -142,554 +139,470 @@ - - al - ca - - - - boolean - Boolean - True + + number + Number + 10000 - - - date - Date - 01.01.2019 + + number_currency + Number currency + 10000 + + currency + + sk_SK + EUR + 2 + + + + + password_data + Password from data + + password + + + + password_dataref + Password from dataRef - taskRef Task Ref - - 4 - - - - file - File - - - textfield: f.text; - change textfield value { - "funguje to" - } - - + + taskref_test_field + Text datafield z iného transitionu + Field načítaný pomocou taskrefu - - - fileList - File List + + text + Text + Lorem ipsum + + + text_area + Text area + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vitae magna in libero semper + vulputate ut eu sapien. Phasellus vel. + + htmltextarea + + red + 12 + + - user User - - + userList1 UserList - userList2 UserList - - - datetime - Datetime - 01.01.2019 20:00 - - - - button - Button - Push - - fab - - - - - taskref_test_field - Text datafield z iného transitionu - Field načítaný pomocou taskrefu - - - 1 + t1 379 273 - + Task - editable auto - - number - Number fields - false - 2 - - number - - editable - - - - number_currency - - editable - - - - - text - Text fields - false - - text - - editable - - - - text_area - - editable - - - - password_data - - editable - - - - password_dataref - - editable - - - password - - - - - enumeration - Enumeration fields - false - - enumeration - - editable - - - - enumeration_autocomplete - - editable - - - - enumeration_list - - editable - - - - enumeration_map - - editable - - - - - multichoice - Multichoice fields - false - - multichoice - - editable - - - - multichoice_list - - editable - - - - multichoice_map - - editable - - - - - boolean - Boolean fields - false - - boolean - - editable - - - - - date - Date fields - false - - date - - editable - - - - datetime - - editable - - - - - file - File fields - false - - file - - editable - - - - fileList - - editable - - - - - user - User fields - false - - user - - editable - - - - - button - Button fields - false - - button - - editable - - generatePdf("1","file") - - - - - - taskRef - Task refs - false - - taskRef - - editable - - - + + t1_flex + + + number + + editable + + + + + + number_currency + + editable + + + + + + text + + editable + + + + + + text_area + + editable + + + + + + password_data + + editable + + + + + + password_dataref + + editable + + + password + + + + + + enumeration + + editable + + + + + + enumeration_autocomplete + + editable + + + + + + enumeration_list + + editable + + + + + + enumeration_map + + editable + + + + + + multichoice + + editable + + + + + + multichoice_list + + editable + + + + + + multichoice_map + + editable + + + + + + boolean + + editable + + + + + + date + + editable + + + + + + datetime + + editable + + + + + + file + + editable + + + + + + fileList + + editable + + + + + + user + + editable + + + + + + button + + editable + + + button_set + + + + + + + + + + + taskRef + + editable + + + + - 2 + t2 379 273 - + Task - visible auto - - number - Number fields - false - - number - - visible - - - - number_currency - - visible - - - - - text - Text fields - false - - text - - visible - - - - text_area - - visible - - - - - enumeration - Enumeration fields - false - - enumeration - - visible - - - - enumeration_autocomplete - - visible - - - - enumeration_list - - visible - - - - enumeration_map - - visible - - - - - multichoice - Multichoice fields - false - - multichoice - - visible - - - - multichoice_list - - visible - - - - multichoice_map - - visible - - - - - boolean - Boolean fields - false - - boolean - - visible - - - - - date - Date fields - false - - date - - visible - - - - datetime - - visible - - - - - file - File fields - false - - file - - visible - - - - fileList - - visible - - - - - user - User fields - false - - user - - visible - - - - - button - Button fields - false - - button - - visible - - - + + t2_flex + + + number + + editable + + + + + + number_currency + + editable + + + + + + text + + editable + + + + + + text_area + + editable + + + + + + enumeration + + editable + + + + + + enumeration_autocomplete + + editable + + + + + + enumeration_list + + editable + + + + + + enumeration_map + + editable + + + + + + multichoice + + editable + + + + + + multichoice_list + + editable + + + + + + multichoice_map + + editable + + + + + + boolean + + editable + + + + + + date + + editable + + + + + + datetime + + editable + + + + + + file + + editable + + + + + + fileList + + editable + + + + + + user + + editable + + + + + + button + + editable + + + + - 3 + t3 379 273 - + Datagroups auto - - stretch - Stretch - start - true - - text - - visible - - - - number - - editable - - - - enumeration - - editable - - - - - right - Alignment - Right - end - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - - - left - Alignment - Left - start - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - - - center - Alignment - Center - center - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - + + t3_flex + + + text + + editable + + + + + + number + + editable + + + + + + enumeration + + editable + + + + - 4 + t4 379 273 - + Task ref test transition auto - - taskref - Task ref test group - - taskref_test_field - - editable - - - + + t4_flex + + + taskref_test_field + + editable + + + + - + \ No newline at end of file diff --git a/src/test/resources/role_cancel_test.xml b/src/test/resources/role_cancel_test.xml deleted file mode 100644 index e0700dbb56a..00000000000 --- a/src/test/resources/role_cancel_test.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - test - TST - Test - - - worker - worker - - - manager - manager - - - - - Task - 0 - 0 - - - worker - - true - - - - manager - - true - - - - - - \ No newline at end of file diff --git a/src/test/resources/rolref_view.xml b/src/test/resources/rolref_view.xml index 4988b7d9d38..e9caba33a28 100644 --- a/src/test/resources/rolref_view.xml +++ b/src/test/resources/rolref_view.xml @@ -1,50 +1,64 @@ - - + test - TST + 1.0.0 Test + false + false + + TST + + + - 1 - View + role1 + View - 2 - Perform + role2 + Perform - 1 + data1 Name - - 1 + t1 300 100 - + Perform - 2 - + role2 + true - + - - 1 - - editable - - + + t1_flex + + + data1 + + editable + + + + 0 + 0 + 1 + + + - 2 + t2 300 180 - + View - 1 - + role1 + true - + - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/rule_engine_test.xml b/src/test/resources/rule_engine_test.xml index 787e57a7470..84af39b27d9 100644 --- a/src/test/resources/rule_engine_test.xml +++ b/src/test/resources/rule_engine_test.xml @@ -1,91 +1,83 @@ - - + rule_engine_test 1.0.0 - RLN Rule engine test process gavel true - false - - - - - text_data - Text - VALUE - + false + + RLN + + + number_data Number 5555 - + + text_data + Text + VALUE + - 2 + t2 340 180 - + Task 1 - 4 + t4 500 180 - + Task 2 - - 1 + p1 220 180 - + init 1 - false - 3 + p3 420 180 - 0 - false - 5 + p5 620 180 - 0 - false - - 6 + a6 regular - 1 - 2 + p1 + t2 1 - 7 + a7 regular - 2 - 3 + t2 + p3 1 - 8 + a8 regular - 3 - 4 + p3 + t4 1 - 9 + a9 regular - 4 - 5 + t4 + p5 1 - + \ No newline at end of file diff --git a/src/test/resources/set_data_test.xml b/src/test/resources/set_data_test.xml deleted file mode 100644 index b3de99d327f..00000000000 --- a/src/test/resources/set_data_test.xml +++ /dev/null @@ -1,3270 +0,0 @@ - - - set_data_test - SDT - Set data test net - - - true - - process_role - Process role - - - - - - number - Number - 10000 - - 1 - - - thisField: f.number, - result: f.number_field_pre_set_result; - - change result value {"Value changed from pre set event, value of number field: " + thisField.value as String} - - - - - thisField: f.number, - result: f.number_field_post_set_result; - - change result value {"Value changed from pre set event, value of number field: " + thisField.value as String} - - - - - - text - Text - Lorem ipsum - - 1 - - - thisField: f.text, - result: f.text_field_pre_set_result; - - change result value {"Value changed from pre set event, value of text field: " + thisField.value as String} - - - - - thisField: f.text, - result: f.text_field_post_set_result; - - change result value {"Value changed from pre set event, value of text field: " + thisField.value as String} - - - - - - text_area - Text area - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vitae magna in libero semper - vulputate ut eu sapien. Phasellus vel. - - - textarea - red - 12 - - - 1 - - - thisField: f.text_area, - result: f.text_area_field_pre_set_result; - - change result value {"Value changed from pre set event, value of text area field: " + thisField.value as String} - - - - - thisField: f.text_area, - result: f.text_area_field_post_set_result; - - change result value {"Value changed from pre set event, value of text area field: " + thisField.value as String} - - - - - - enumeration - Enumeration - Alice - Bob - Carol - Bob - - 1 - - - thisField: f.enumeration, - result: f.enumeration_field_pre_set_result; - - change result value {"Value changed from pre set event, value of enumeration field: " + thisField.value as String} - - - - - thisField: f.enumeration, - result: f.enumeration_field_post_set_result; - - change result value {"Value changed from post set event, value of enumeration field: " + thisField.value as String} - - - - - - enumeration_map - Enumeration Map - - - - - - - al - ca - - - 1 - - - thisField: f.enumeration_map, - result: f.enumeration_map_field_pre_set_result; - - change result value {"Value changed from pre set event, value of enumeration map field: " + thisField.value as String} - - - - - thisField: f.enumeration_map, - result: f.enumeration_map_field_post_set_result; - - change result value {"Value changed from pre post event, value of enumeration map field: " + thisField.value as String} - - - - - - multichoice - Multichoice - Alice - Bob - Carol - - Bob - - - 1 - - - thisField: f.multichoice, - result: f.multichoice_field_pre_set_result; - - change result value {"Value changed from pre set event, value of multichoice field: " + thisField.value as String} - - - - - thisField: f.multichoice, - result: f.multichoice_field_post_set_result; - - change result value {"Value changed from post set event, value of multichoice field: " + thisField.value as String} - - - - - - multichoice_map - Multichoice Map - - - - - - - al - bo - - - 1 - - - thisField: f.multichoice_map, - result: f.multichoice_map_field_pre_set_result; - - change result value {"Value changed from pre set event, value of multichoice map field: " + thisField.value as String} - - - - - thisField: f.multichoice_map, - result: f.multichoice_map_field_post_set_result; - - change result value {"Value changed from post set event, value of multichoice map field: " + thisField.value as String} - - - - - - boolean - Boolean - True - false - - 1 - - - thisField: f.boolean, - result: f.boolean_field_pre_set_result; - - change result value {"Value changed from pre set event, value of boolean field: " + thisField.value as String} - - - - - thisField: f.boolean, - result: f.boolean_field_post_set_result; - - change result value {"Value changed from post set event, value of boolean field: " + thisField.value as String} - - - - - - date - Date - 2018-12-31T23:00:00.000Z - - 1 - - - thisField: f.date, - result: f.date_field_pre_set_result; - - change result value {"Value changed from pre set event, value of date field: " + thisField.value as String} - - - - - thisField: f.date, - result: f.date_field_post_set_result; - - change result value {"Value changed from post set event, value of date field: " + thisField.value as String} - - - - - - taskRef - Task Ref - - - file - File - - 1 - - - thisField: f.file, - result: f.file_field_pre_set_result; - - change result value {"Value changed from pre set event, value of file field: " + thisField.value?.name as String} - - - - - thisField: f.file, - result: f.file_field_post_set_result; - - change result value {"Value changed from post set event, value of file field: " + thisField.value?.name as String} - - - - - - fileList - File List - - 1 - - - thisField: f.fileList, - result: f.filelist_field_pre_set_result; - - change result value {"Value changed from pre set event, value of file list field: " + (thisField.value?.namesPaths as Set).stream().map({ value -> value.name }).collect(java.util.stream.Collectors.toList()) as String} - - - - - thisField: f.fileList, - result: f.filelist_field_post_set_result; - - change result value { "Value changed from post set event, value of file list field: " + (thisField.value?.namesPaths as Set).stream().map({ value -> value.name }).collect(java.util.stream.Collectors.toList()) as String } - - - - - - user - User - - 1 - - - thisField: f.user, - result: f.user_field_pre_set_result; - - change result value {"Value changed from pre set event, value of user field: " + thisField.value?.name + " " + thisField.value?.surname} - - - - - thisField: f.user, - result: f.user_field_post_set_result; - - change result value {"Value changed from post set event, value of user field: " + thisField.value?.name + " " + thisField.value?.surname} - - - - - - datetime - Datetime - 2019-01-01T19:00:00.000Z - - 1 - - - thisField: f.datetime, - result: f.datetime_field_pre_set_result; - - change result value {"Value changed from pre set event, value of datetime field: " + thisField.value as String} - - - - - thisField: f.datetime, - result: f.datetime_field_post_set_result; - - change result value {"Value changed from post set event, value of datetime field: " + thisField.value as String} - - - - - - button - Button - Push - - raised - - - 1 - - - thisField: f.button, - result: f.button_field_pre_set_result; - - change result value {"Value changed from pre set event, value of button field: " + thisField.value as String} - - - - - thisField: f.button, - result: f.button_field_post_set_result; - - change result value {"Value changed from post set event, value of button field: " + thisField.value as String} - - - - - - number_field_pre_set_result - Number field pre set event result - No value from pre set event - - - number_field_post_set_result - Number field post set event result - No value from post set event - - - number_field_visibility - Change number field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.number; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" })) { - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" }) || - (useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "hidden" })) - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - number_field_hide - Hide number field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.number; - - make mainField, hidden on trans when {true} - - - - - - number_field_required - Change number field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.number; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - text_field_pre_set_result - Text field pre set event result - No value from pre set event - - - text_field_post_set_result - Text field post set event result - No value from post set event - - - text_field_visibility - Change text field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.text; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})){ - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - text_field_hide - Hide text field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.text; - - make mainField, hidden on trans when {true} - - - - - - text_field_required - Change text field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.text; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - text_area_field_visibility - Change text area field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.text_area; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})) { - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - text_area_field_hide - Hide text area field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.text_area; - - make mainField, hidden on trans when {true} - - - - - - text_area_field_required - Change text area field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.text_area; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - text_area_field_pre_set_result - Text area field pre set event result - No value from pre set event - - - text_area_field_post_set_result - Text area field post set event result - No value from post set event - - - enumeration_field_pre_set_result - Enumeration field pre set event result - No value from pre set event - - - enumeration_field_post_set_result - Enumeration field post set event result - No value from post set event - - - enumeration_field_visibility - Change enumeration field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.enumeration; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})) { - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - enumeration_field_hide - Hide enumeration field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.enumeration; - - make mainField, hidden on trans when {true} - - - - - - enumeration_field_required - Change enumeration field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.enumeration; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - clear_event_values - Clear event result values - Clear event result values - - raised - - - 1 - - - def fieldMap = [ - "result1":"number_field_pre_set_result", - "result2":"number_field_post_set_result", - "result3":"text_field_pre_set_result", - "result4":"text_field_post_set_result", - "result5":"text_area_field_pre_set_result", - "result6":"text_area_field_post_set_result", - "result7":"enumeration_field_pre_set_result", - "result8":"enumeration_field_post_set_result", - "result9":"enumeration_map_field_pre_set_result", - "result10":"enumeration_map_field_post_set_result", - "result11":"multichoice_field_pre_set_result", - "result12":"multichoice_field_post_set_result", - "result13":"multichoice_map_field_pre_set_result", - "result14":"multichoice_map_field_post_set_result", - "result15":"boolean_field_pre_set_result", - "result16":"boolean_field_post_set_result", - "result17":"date_field_pre_set_result", - "result18":"date_field_post_set_result", - "result19":"datetime_field_pre_set_result", - "result20":"datetime_field_post_set_result", - "result21":"file_field_pre_set_result", - "result22":"file_field_post_set_result", - "result23":"filelist_field_pre_set_result", - "result24":"filelist_field_post_set_result", - "result25":"user_field_pre_set_result", - "result26":"user_field_post_set_result", - "result27":"button_field_pre_set_result", - "result28":"button_field_post_set_result" - ] - - for(i in 1..< 29) { - if(i % 2 == 1){ - change useCase.getField(fieldMap["result" + (i as String)]) value { "No value from pre set event" } - } else { - change useCase.getField(fieldMap["result" + (i as String)]) value { "No value from post set event" } - } - } - - - - - - - enumeration_map_field_pre_set_result - Enumeration map field pre set event result - No value from pre set event - - - enumeration_map_field_post_set_result - Enumeration map field post set event result - No value from post set event - - - enumeration_map_field_visibility - Change enumeration map field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.enumeration_map; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})) { - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - enumeration_map_field_hide - Hide enumeration map field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.enumeration_map; - - make mainField, hidden on trans when {true} - - - - - - enumeration_map_field_required - Change enumeration map field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.enumeration_map; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - enumeration_map_field_options - Change enumeration field options - Change options - - raised - - - 1 - - - thisField: f.enumeration_map; - - if ( thisField.options.size() > 3){ - change thisField options { [ - "al":new com.netgrif.application.engine.petrinet.domain.I18nString("Alice"), - "bo":new com.netgrif.application.engine.petrinet.domain.I18nString("Bob"), - "ca":new com.netgrif.application.engine.petrinet.domain.I18nString("Carol") - ]} - } else { - change thisField options { [ - "jo":new com.netgrif.application.engine.petrinet.domain.I18nString("Jozef"), - "ju":new com.netgrif.application.engine.petrinet.domain.I18nString("Juraj"), - "sa":new com.netgrif.application.engine.petrinet.domain.I18nString("Samuel"), - "on":new com.netgrif.application.engine.petrinet.domain.I18nString("Ondrej"), - "mi":new com.netgrif.application.engine.petrinet.domain.I18nString("Milan") - ] } - } - - - - - - enumeration_field_choices - Change enumeration field choices - Change choices - - raised - - - 1 - - - thisField: f.enumeration; - - if ( thisField.choices.size() > 3){ - change thisField choices { [ - new com.netgrif.application.engine.petrinet.domain.I18nString("Alice"), - new com.netgrif.application.engine.petrinet.domain.I18nString("Bob"), - new com.netgrif.application.engine.petrinet.domain.I18nString("Carol") - ] } - } else { - change thisField choices { [ - new com.netgrif.application.engine.petrinet.domain.I18nString("Jozef"), - new com.netgrif.application.engine.petrinet.domain.I18nString("Juraj"), - new com.netgrif.application.engine.petrinet.domain.I18nString("Samuel"), - new com.netgrif.application.engine.petrinet.domain.I18nString("Ondrej"), - new com.netgrif.application.engine.petrinet.domain.I18nString("Milan") - ] } - } - - - - - - multichoice_field_pre_set_result - Multichoice field pre set event result - No value from pre set event - - - multichoice_field_post_set_result - Multichoice field post set event result - No value from post set event - - - multichoice_field_visibility - Change multichoice field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.multichoice; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})) { - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - multichoice_field_hide - Hide multichoice field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.multichoice; - - make mainField, hidden on trans when {true} - - - - - - multichoice_field_required - Change multichoice field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.multichoice; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - multichoice_field_choices - Change multichoice field choices - Change choices - - raised - - - 1 - - - thisField: f.multichoice; - - if ( thisField.choices.size() > 3){ - change thisField choices { [ - new com.netgrif.application.engine.petrinet.domain.I18nString("Alice"), - new com.netgrif.application.engine.petrinet.domain.I18nString("Bob"), - new com.netgrif.application.engine.petrinet.domain.I18nString("Carol") - ] } - } else { - change thisField choices { [ - new com.netgrif.application.engine.petrinet.domain.I18nString("Jozef"), - new com.netgrif.application.engine.petrinet.domain.I18nString("Juraj"), - new com.netgrif.application.engine.petrinet.domain.I18nString("Samuel"), - new com.netgrif.application.engine.petrinet.domain.I18nString("Ondrej"), - new com.netgrif.application.engine.petrinet.domain.I18nString("Milan") - ] } - } - - - - - - multichoice_map_field_pre_set_result - Multichoice map field pre set event result - No value from pre set event - - - multichoice_map_field_post_set_result - Multichoice map field post set event result - No value from post set event - - - multichoice_map_field_visibility - Change multichoice map field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.multichoice_map; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})) { - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - multichoice_map_field_hide - Hide multichoice map field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.multichoice_map; - - make mainField, hidden on trans when {true} - - - - - - multichoice_map_field_required - Change multichoice map field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.multichoice_map; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - multichoice_map_field_options - Change multichoice map field options - Change options - - raised - - - 1 - - - thisField: f.multichoice_map; - - if ( thisField.options.size() > 3){ - change thisField options { [ - "al":new com.netgrif.application.engine.petrinet.domain.I18nString("Alice"), - "bo":new com.netgrif.application.engine.petrinet.domain.I18nString("Bob"), - "ca":new com.netgrif.application.engine.petrinet.domain.I18nString("Carol") - ]} - } else { - change thisField options { [ - "jo":new com.netgrif.application.engine.petrinet.domain.I18nString("Jozef"), - "ju":new com.netgrif.application.engine.petrinet.domain.I18nString("Juraj"), - "sa":new com.netgrif.application.engine.petrinet.domain.I18nString("Samuel"), - "on":new com.netgrif.application.engine.petrinet.domain.I18nString("Ondrej"), - "mi":new com.netgrif.application.engine.petrinet.domain.I18nString("Milan") - ] } - } - - - - - - date_field_pre_set_result - Date field pre set event result - No value from pre set event - - - date_field_post_set_result - Date field post set event result - No value from post set event - - - date_field_visibility - Change date field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.date; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})) { - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - date_field_hide - Hide date field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.date; - - make mainField, hidden on trans when {true} - - - - - - date_field_required - Change date field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.date; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - datetime_field_pre_set_result - Datetime field pre set event result - No value from pre set event - - - datetime_field_post_set_result - Datetime field post set event result - No value from post set event - - - datetime_field_visibility - Change datetime field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.datetime; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})) { - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - datetime_field_hide - Hide datetime field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.datetime; - - make mainField, hidden on trans when {true} - - - - - - datetime_field_required - Change datetime field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.datetime; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - boolean_field_pre_set_result - Boolean field pre set event result - No value from pre set event - - - boolean_field_post_set_result - Boolean field post set event result - No value from post set event - - - boolean_field_visibility - Change boolean field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.boolean; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})) { - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - boolean_field_hide - Hide boolean field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.boolean; - - make mainField, hidden on trans when {true} - - - - - - boolean_field_required - Change boolean field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.boolean; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - file_field_visibility - Change file field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.file; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})) { - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - file_field_hide - Hide file field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.file; - - make mainField, hidden on trans when {true} - - - - - - file_field_required - Change file field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.file; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - file_field_pre_set_result - File field pre set event result - No value from pre set event - - - file_field_post_set_result - File field post set event result - No value from post set event - - - filelist_field_pre_set_result - Filelist field pre set event result - No value from pre set event - - - filelist_field_post_set_result - Filelist field post set event result - No value from post set event - - - filelist_field_visibility - Change filelist field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.fileList; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})) { - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - filelist_field_hide - Hide filelist field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.fileList; - - make mainField, hidden on trans when {true} - - - - - - filelist_field_required - Change filelist field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.fileList; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - user_field_pre_set_result - User field pre set event result - No value from pre set event - - - user_field_post_set_result - User field post set event result - No value from post set event - - - user_field_visibility - Change user field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.user; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})) { - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - user_field_hide - Hide user field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.user; - - make mainField, hidden on trans when {true} - - - - - - user_field_required - Change user field requirability - Required/optional - - raised - - - 1 - - - trans: t.1, - mainField: f.user; - - if ((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden" || fieldBehavior.toString() == "optional" })) { - make mainField, required on trans when {true} - } else { - make mainField, optional on trans when {true} - } - - - - - - button_field_visibility - Change button field editability - Editable/visible - - raised - - - 1 - - - trans: t.1, - mainField: f.button; - - if((useCase.dataSet[mainField.stringId].behavior["1"] as Set).any({ fieldBehavior -> fieldBehavior.toString() == "visible" || fieldBehavior.toString() == "hidden"})) { - make mainField, editable on trans when {true} - } else { - make mainField, visible on trans when {true} - } - - - - - - button_field_hide - Hide button field - Hidden - - raised - - - 1 - - - trans: t.1, - mainField: f.button; - - make mainField, hidden on trans when {true} - - - - - - button_field_pre_set_result - User button pre set event result - No value from pre set event - - - button_field_post_set_result - User button post set event result - No value from post set event - - - - - 1 - 282 - 63 - - 6 - 0 - - - auto - - number - grid - Number - false - - number - - editable - required - - - 0 - 1 - 1 - 2 - 0 - - outline - - - - number_field_pre_set_result - - visible - optional - - - 2 - 1 - 1 - 2 - 0 - - outline - - - - number_field_post_set_result - - visible - optional - - - 4 - 1 - 1 - 2 - 0 - - outline - - - - number_field_visibility - - editable - - - 0 - 2 - 1 - 2 - 0 - - - - - number_field_hide - - editable - - - 2 - 2 - 1 - 2 - 0 - - - - - number_field_required - - editable - - - 4 - 2 - 1 - 2 - 0 - - - - - - text - Text - grid - false - - text - - editable - required - - - 0 - 4 - 1 - 2 - 0 - - outline - - - - text_field_pre_set_result - - visible - optional - - - 2 - 4 - 1 - 2 - 0 - - outline - - - - text_field_post_set_result - - visible - optional - - - 4 - 4 - 1 - 2 - 0 - - outline - - - - text_field_visibility - - editable - - - 0 - 5 - 1 - 2 - 0 - - - - - text_field_hide - - editable - - - 2 - 5 - 1 - 2 - 0 - - - - - text_field_required - - editable - - - 4 - 5 - 1 - 2 - 0 - - - - - - text_area - Text area - grid - - text_area - - editable - required - - - 0 - 7 - 1 - 2 - 0 - - outline - - - - text_area_field_pre_set_result - - visible - optional - - - 2 - 7 - 1 - 2 - 0 - - outline - - - - text_area_field_post_set_result - - visible - optional - - - 4 - 7 - 1 - 2 - 0 - - outline - - - - text_area_field_visibility - - editable - - - 0 - 8 - 1 - 2 - 0 - - - - - text_area_field_hide - - editable - - - 2 - 8 - 1 - 2 - 0 - - - - - text_area_field_required - - editable - - - 4 - 8 - 1 - 2 - 0 - - - - - - enum - Enumeration - grid - - enumeration - - editable - required - - - 0 - 10 - 1 - 2 - 0 - - outline - - - - enumeration_field_pre_set_result - - visible - optional - - - 2 - 10 - 1 - 2 - 0 - - outline - - - - enumeration_field_post_set_result - - visible - optional - - - 4 - 10 - 1 - 2 - 0 - - outline - - - - enumeration_field_visibility - - editable - - - 0 - 11 - 1 - 2 - 0 - - - - - enumeration_field_hide - - editable - - - 2 - 11 - 1 - 2 - 0 - - - - - enumeration_field_required - - editable - - - 4 - 11 - 1 - 2 - 0 - - - - - enumeration_field_choices - - editable - - - 0 - 12 - 1 - 2 - 0 - - - - - - enum_map - Enumeration map - grid - - enumeration_map - - editable - required - - - 0 - 14 - 1 - 2 - 0 - - outline - - - - enumeration_map_field_pre_set_result - - visible - optional - - - 2 - 14 - 1 - 2 - 0 - - outline - - - - enumeration_map_field_post_set_result - - visible - optional - - - 4 - 14 - 1 - 2 - 0 - - outline - - - - enumeration_map_field_visibility - - editable - - - 0 - 15 - 1 - 2 - 0 - - - - - enumeration_map_field_hide - - editable - - - 2 - 15 - 1 - 2 - 0 - - - - - enumeration_map_field_required - - editable - - - 4 - 15 - 1 - 2 - 0 - - - - - enumeration_map_field_options - - editable - - - 0 - 16 - 1 - 2 - 0 - - - - - - multichoice - Multichoice - grid - - multichoice - - editable - required - - - 0 - 18 - 1 - 2 - 0 - - outline - - - - multichoice_field_pre_set_result - - visible - optional - - - 2 - 18 - 1 - 2 - 0 - - outline - - - - multichoice_field_post_set_result - - visible - optional - - - 4 - 18 - 1 - 2 - 0 - - outline - - - - multichoice_field_visibility - - editable - - - 0 - 19 - 1 - 2 - 0 - - - - - multichoice_field_hide - - editable - - - 2 - 19 - 1 - 2 - 0 - - - - - multichoice_field_required - - editable - - - 4 - 19 - 1 - 2 - 0 - - - - - multichoice_field_choices - - editable - - - 0 - 20 - 1 - 2 - 0 - - - - - - multichoice_map - Multichoice map - grid - - multichoice_map - - editable - required - - - 0 - 22 - 1 - 2 - 0 - - outline - - - - multichoice_map_field_pre_set_result - - visible - optional - - - 2 - 22 - 1 - 2 - 0 - - outline - - - - multichoice_map_field_post_set_result - - visible - optional - - - 4 - 22 - 1 - 2 - 0 - - outline - - - - multichoice_map_field_visibility - - editable - - - 0 - 23 - 1 - 2 - 0 - - - - - multichoice_map_field_hide - - editable - - - 2 - 23 - 1 - 2 - 0 - - - - - multichoice_map_field_required - - editable - - - 4 - 23 - 1 - 2 - 0 - - - - - multichoice_map_field_options - - editable - - - 0 - 24 - 1 - 2 - 0 - - - - - - boolean - Boolean - grid - - boolean - - editable - - - 0 - 26 - 1 - 2 - 0 - - - - - boolean_field_pre_set_result - - visible - optional - - - 2 - 26 - 1 - 2 - 0 - - outline - - - - boolean_field_post_set_result - - visible - optional - - - 4 - 26 - 1 - 2 - 0 - - outline - - - - boolean_field_visibility - - editable - - - 0 - 27 - 1 - 2 - 0 - - - - - boolean_field_hide - - editable - - - 2 - 27 - 1 - 2 - 0 - - - - - boolean_field_required - - editable - - - 4 - 27 - 1 - 2 - 0 - - - - - - date - Date - grid - - date - - editable - required - - - 0 - 29 - 1 - 2 - 0 - - outline - - - - date_field_pre_set_result - - visible - optional - - - 2 - 29 - 1 - 2 - 0 - - outline - - - - date_field_post_set_result - - visible - optional - - - 4 - 29 - 1 - 2 - 0 - - outline - - - - date_field_visibility - - editable - - - 0 - 30 - 1 - 2 - 0 - - - - - date_field_hide - - editable - - - 2 - 30 - 1 - 2 - 0 - - - - - date_field_required - - editable - - - 4 - 30 - 1 - 2 - 0 - - - - - - datetime - Datetime - grid - - datetime - - editable - required - - - 0 - 32 - 1 - 2 - 0 - - outline - - - - datetime_field_pre_set_result - - visible - optional - - - 2 - 32 - 1 - 2 - 0 - - outline - - - - datetime_field_post_set_result - - visible - optional - - - 4 - 32 - 1 - 2 - 0 - - outline - - - - datetime_field_visibility - - editable - - - 0 - 33 - 1 - 2 - 0 - - - - - datetime_field_hide - - editable - - - 2 - 33 - 1 - 2 - 0 - - - - - datetime_field_required - - editable - - - 4 - 33 - 1 - 2 - 0 - - - - - - file - File - grid - - file - - editable - optional - - - 0 - 35 - 1 - 2 - 0 - - - - - file_field_pre_set_result - - visible - optional - - - 2 - 35 - 1 - 2 - 0 - - outline - - - - file_field_post_set_result - - visible - optional - - - 4 - 35 - 1 - 2 - 0 - - outline - - - - file_field_visibility - - editable - - - 0 - 36 - 1 - 2 - 0 - - - - - file_field_hide - - editable - - - 2 - 36 - 1 - 2 - 0 - - - - - file_field_required - - editable - - - 4 - 36 - 1 - 2 - 0 - - - - - - file_list - File list - grid - - fileList - - editable - required - - - 0 - 38 - 1 - 2 - 0 - - - - - filelist_field_pre_set_result - - visible - optional - - - 2 - 38 - 1 - 2 - 0 - - outline - - - - filelist_field_post_set_result - - visible - optional - - - 4 - 38 - 1 - 2 - 0 - - outline - - - - filelist_field_visibility - - editable - - - 0 - 39 - 1 - 2 - 0 - - - - - filelist_field_hide - - editable - - - 2 - 39 - 1 - 2 - 0 - - - - - filelist_field_required - - editable - - - 4 - 39 - 1 - 2 - 0 - - - - - - user - User - grid - - user - - editable - required - - - 0 - 41 - 1 - 2 - 0 - - outline - - - - user_field_pre_set_result - - visible - optional - - - 2 - 41 - 1 - 2 - 0 - - outline - - - - user_field_post_set_result - - visible - optional - - - 4 - 41 - 1 - 2 - 0 - - outline - - - - user_field_visibility - - editable - - - 0 - 42 - 1 - 2 - 0 - - - - - user_field_hide - - editable - - - 2 - 42 - 1 - 2 - 0 - - - - - user_field_required - - editable - - - 4 - 42 - 1 - 2 - 0 - - - - - - button - Button - grid - - button - - editable - - - - - - - 0 - 44 - 1 - 2 - 0 - - - - - button_field_pre_set_result - - visible - optional - - - 2 - 44 - 1 - 2 - 0 - - outline - - - - button_field_post_set_result - - visible - optional - - - 4 - 44 - 1 - 2 - 0 - - outline - - - - button_field_visibility - - editable - - - 0 - 45 - 1 - 2 - 0 - - - - - button_field_hide - - editable - - - 2 - 45 - 1 - 2 - 0 - - - - - - clear - grid - Clear values - - clear_event_values - - editable - - - 0 - 46 - 1 - 6 - 0 - - - - - - - 2 - 283 - 146 - - 0 - - - auto - - number - Number fields - false - - number - - visible - - - - - text - Text fields - false - - text - - visible - - - - text_area - - visible - - - - - enumeration - Enumeration fields - false - - enumeration - - visible - - - - enumeration_map - - visible - - - - - multichoice - Multichoice fields - false - - multichoice - - visible - - - - multichoice_map - - visible - - - - - boolean - Boolean fields - false - - boolean - - visible - - - - - date - Date fields - false - - date - - visible - - - - datetime - - visible - - - - - file - File fields - false - - file - - visible - - - - fileList - - visible - - - - - user - User fields - false - - user - - visible - - - - - button - Button fields - false - - button - - visible - - - - - - 3 - 281 - 229 - - 0 - - - auto - - stretch - Stretch - start - true - - text - - visible - - - - number - - editable - - - - enumeration - - editable - - - - - right - Alignment - Right - end - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - - - left - Alignment - Left - start - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - - - center - Alignment - Center - center - false - - text - - visible - - - - number - - visible - - - - enumeration - - visible - - - - - - 4 - 281 - 307 - - 0 - - - auto - - taskref - Task ref test group - - taskref_test_field - - editable - - - - - - - diff --git a/src/test/resources/simple_taskref.xml b/src/test/resources/simple_taskref.xml deleted file mode 100644 index 423f9100e8d..00000000000 --- a/src/test/resources/simple_taskref.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - simple_taskref - STR - simple taskref - true - false - - - - newRole_1 - - - - - - - text_0 - Field top - - - text_1 - Field bot - - - taskRef_0 - - t2 - - - text_2 - Reffed - - - - - t1 - 660 - 340 - - 0 - - - - DataGroup1 - grid - - text_0 - - editable - - - 0 - 0 - 1 - 4 - 0 - - outline - - - - text_1 - - editable - - - 0 - 2 - 1 - 4 - 0 - - outline - - - - taskRef_0 - - editable - - - 0 - 1 - 1 - 4 - 0 - - outline - - - - - - t2 - 900 - 340 - - 0 - - - - newRole_1 - - true - - - - DataGroup2 - grid - - text_2 - - editable - - - 0 - 0 - 1 - 4 - 0 - - outline - - - - - - - diff --git a/src/test/resources/taskRefLayoutTest.xml b/src/test/resources/taskRefLayoutTest.xml deleted file mode 100644 index 3897d40fadc..00000000000 --- a/src/test/resources/taskRefLayoutTest.xml +++ /dev/null @@ -1,168 +0,0 @@ - - - taskRefLayoutTest - 1.0.0 - NEW - taskRefLayoutTest - home - true - false - - - - - - taskRef - TaskRef - - taskRef : f.this; - - def list = [] -// TODO: release/8.0.0 fix mongo search by data - findCases { it.processIdentifier.eq("priloha") }.findAll { it.dataSet["requestID"].value == useCase.stringId - }.each { list.addAll(it.tasks.collect { it.task }) }.sort{ it.creationDate } - change taskRef value { list } - - - - buttonicek - - Chuju - - taskRef : f.taskRef; - - def aPriloha = createCase("priloha") - aPriloha.dataSet.get("requestID").setValue(useCase.stringId) - workflowService.save(aPriloha) - def list = [] - // TODO: release/8.0.0 fix mongo search by data - findCases { it.processIdentifier.eq("priloha") }.findAll { it.dataSet["requestID"].value == useCase.stringId - }.each { list.addAll(it.tasks.collect { it.task }) }.sort{ it.creationDate } - change taskRef value { list } - - - - temp00 - Temp00 - - - temp01 - Temp00 - - - temp1 - Temp1 - - - temp2 - Temp2 - - - 2 - 670 - 231 - - - temp00 - - editable - - - 0 - 0 - 1 - 2 - - outline - - - - temp01 - - editable - - - 2 - 0 - 1 - 2 - - outline - - - - taskRef - - editable - - - 0 - 1 - 1 - 4 - - outline - - - - buttonicek - - editable - - - 0 - 2 - 1 - 4 - - outline - - - - temp1 - - editable - - - 0 - 3 - 1 - 4 - - outline - - - - temp2 - - editable - - - 0 - 4 - 1 - 4 - - outline - - - - - - 1 - 459 - 231 - - 1 - false - - - - 3 - regular - 1 - 2 - 1 - - diff --git a/src/test/resources/taskRefLayoutTest2.xml b/src/test/resources/taskRefLayoutTest2.xml deleted file mode 100644 index c7ec7ac018a..00000000000 --- a/src/test/resources/taskRefLayoutTest2.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - taskRefLayoutTest2 - 1.0.0 - NEW - taskRefLayoutTest2 - home - true - false - - - - - - taskRef - TaskRef - - - taskRef : f.this; - - def list = [] - // TODO: release/8.0.0 fix mongo search by data - findCases { it.processIdentifier.eq("priloha") }.findAll { it.dataSet["requestID"].value == useCase.stringId - }.each { list.addAll(it.tasks.values().collect { it.task }) }.sort{ it.creationDate } - change taskRef value { list } - - - - - buttonicek - - Button - - - taskRef : f.taskRef; - - def aPriloha = createCase("priloha") - aPriloha.dataSet.get("requestID").rawValue = useCase.stringId - workflowService.save(aPriloha) - def list = [] - // TODO: release/8.0.0 fix mongo search by data - findCases { it.processIdentifier.eq("priloha") }.findAll { it.dataSet["requestID"].value == useCase.stringId - }.each { list.addAll(it.tasks.values().collect { it.task }) }.sort{ it.creationDate } - change taskRef value { list } - - - - - temp00 - Temp00 - - - temp01 - Temp00 - - - temp1 - Temp1 - - - temp2 - Temp2 - - - 2 - 670 - 231 - - - taskRef - - editable - - - 0 - 0 - 1 - 4 - - outline - - - - buttonicek - - editable - - - 0 - 1 - 1 - 2 - - outline - - - - temp1 - - editable - - - 0 - 2 - 1 - 4 - - outline - - - - - - 1 - 459 - 231 - - 1 - false - - - - 3 - regular - 1 - 2 - 1 - - diff --git a/src/test/resources/taskRefLayoutTest3.xml b/src/test/resources/taskRefLayoutTest3.xml deleted file mode 100644 index 8cede4b1de9..00000000000 --- a/src/test/resources/taskRefLayoutTest3.xml +++ /dev/null @@ -1,166 +0,0 @@ - - - taskRefLayoutTest3 - 1.0.0 - NEW - taskRefLayoutTest3 - home - true - false - - - - - - taskRef - TaskRef - - taskRef : f.this; - - def list = [] - findCases { it.processIdentifier.eq("priloha") }.findAll { it.dataSet["requestID"].value == useCase.stringId - }.each { list.addAll(it.tasks.collect { it.task }) }.sort{ it.creationDate } - change taskRef value { list } - - - - buttonicek - - Chuju - - taskRef : f.taskRef; - - def aPriloha = createCase("priloha") - aPriloha.dataSet.get("requestID").setValue(useCase.stringId) - workflowService.save(aPriloha) - def list = [] - findCases { it.processIdentifier.eq("priloha") }.findAll { it.dataSet["requestID"].value == useCase.stringId - }.each { list.addAll(it.tasks.collect { it.task }) }.sort{ it.creationDate } - change taskRef value { list } - - - - temp00 - Temp00 - - - temp01 - Temp00 - - - temp1 - Temp1 - - - temp2 - Temp2 - - - 2 - 670 - 231 - - - temp00 - - editable - - - 0 - 0 - 1 - 2 - - outline - - - - temp01 - - editable - - - 2 - 0 - 1 - 2 - - outline - - - - taskRef - - editable - - - 0 - 1 - 1 - 4 - - outline - - - - buttonicek - - editable - - - 0 - 2 - 1 - 4 - - outline - - - - temp1 - - editable - - - 0 - 3 - 1 - 4 - - outline - - - - temp2 - - editable - - - 0 - 4 - 1 - 4 - - outline - - - - - - 1 - 459 - 231 - - 1 - false - - - - 3 - regular - 1 - 2 - 1 - - diff --git a/src/test/resources/taskRefLayoutTest4.xml b/src/test/resources/taskRefLayoutTest4.xml deleted file mode 100644 index dca0763f449..00000000000 --- a/src/test/resources/taskRefLayoutTest4.xml +++ /dev/null @@ -1,166 +0,0 @@ - - - taskRefLayoutTest3 - 1.0.0 - NEW - taskRefLayoutTest - home - true - false - - - - - - taskRef - TaskRef - - taskRef : f.this; - - def list = [] - findCases { it.processIdentifier.eq("priloha") }.findAll { it.dataSet["requestID"].value == useCase.stringId - }.each { list.addAll(it.tasks.collect { it.task }) }.sort{ it.creationDate } - change taskRef value { list } - - - - buttonicek - - Chuju - - taskRef : f.taskRef; - - def aPriloha = createCase("priloha") - aPriloha.dataSet.get("requestID").setValue(useCase.stringId) - workflowService.save(aPriloha) - def list = [] - findCases { it.processIdentifier.eq("priloha") }.findAll { it.dataSet["requestID"].value == useCase.stringId - }.each { list.addAll(it.tasks.collect { it.task }) }.sort{ it.creationDate } - change taskRef value { list } - - - - temp00 - Temp00 - - - temp01 - Temp00 - - - temp1 - Temp1 - - - temp2 - Temp2 - - - 2 - 670 - 231 - - - temp00 - - editable - - - 0 - 0 - 1 - 2 - - outline - - - - temp01 - - editable - - - 2 - 0 - 1 - 2 - - outline - - - - taskRef - - editable - - - 0 - 1 - 1 - 4 - - outline - - - - buttonicek - - editable - - - 0 - 2 - 1 - 4 - - outline - - - - temp1 - - editable - - - 0 - 3 - 1 - 4 - - outline - - - - temp2 - - editable - - - 0 - 4 - 1 - 4 - - outline - - - - - - 1 - 459 - 231 - - 1 - false - - - - 3 - regular - 1 - 2 - 1 - - diff --git a/src/test/resources/taskRef_propagation_test_child.xml b/src/test/resources/taskRef_propagation_test_child.xml index 2a56be1d167..84b3910f7a1 100644 --- a/src/test/resources/taskRef_propagation_test_child.xml +++ b/src/test/resources/taskRef_propagation_test_child.xml @@ -1,16 +1,15 @@ - - + child 1.0.0 - CHL child home true - false - - - + false + + CHL + + + parentId Parent id @@ -18,164 +17,258 @@ text1 Text1 - - - text1: f.text1, - text2: f.text2; - - change text2 value { text1.value } - + + text1_set + + + + + + text2 Text2 - - - text2: f.text2, - parentId: f.parentId; - - def parentCase = workflowService.findOne(parentId.value) - setDataWithPropagation("2", parentCase, [ - "text_from_child_setter": ["type": "text", "value": (text2.value + "-propagated-up") as String] - ]) - + + text2_set + + + + + + text3 Text3 - - - text4: f.text4; - - change text4 value { "TEXT_4_VALUE" } - + + text3_set + + + + + + text4 Text4 - text5 Text5 - - - text5: f.text5, - parentId: f.parentId; - - def parentCase = workflowService.findOne(parentId.value) - setDataWithPropagation("2", parentCase, [ - "multichoice_setter": ["type": "text", "value": (text5.value) as String] - ]) - - + + text5_set + + + + + + text6 Text6 - - - text6: f.text6, - parentId: f.parentId; - - def parentCase = workflowService.findOne(parentId.value) - setDataWithPropagation("2", parentCase, [ - "multichoice": ["type": "multichoice", "value": [text6.value] as List] - ]) - + + text6_set + + + + + + - - - 2 + t2 580 220 - - - text1 - - editable - - - - text2 - - editable - - - - text3 - - editable - - - - text4 - - editable - - - - text5 - - editable - - - - text6 - - editable - - + Task 1 + + t2_flex + + + text1 + + editable + + + + 0 + 0 + 1 + + + + + text2 + + editable + + + + 0 + 0 + 1 + + + + + text3 + + editable + + + + 0 + 0 + 1 + + + + + text4 + + editable + + + + 0 + 0 + 1 + + + + + text5 + + editable + + + + 0 + 0 + 1 + + + + + text6 + + editable + + + + 0 + 0 + 1 + + + - - 4 + t4 780 220 - - - 0 - Údaje inštancie - - text1 - - editable - - - - text2 - - editable - - - - text3 - - editable - - - - text4 - - editable - - - - text5 - - editable - - - - text6 - - editable - - - - + Task 2 + + t4_flex + + + text1 + + editable + + + + 0 + 0 + 1 + + + + + text2 + + editable + + + + 0 + 0 + 1 + + + + + text3 + + editable + + + + 0 + 0 + 1 + + + + + text4 + + editable + + + + 0 + 0 + 1 + + + + + text5 + + editable + + + + 0 + 0 + 1 + + + + + text6 + + editable + + + + 0 + 0 + 1 + + + - - - + \ No newline at end of file diff --git a/src/test/resources/taskRef_propagation_test_parent.xml b/src/test/resources/taskRef_propagation_test_parent.xml index 04d00788b99..94cefe4df20 100644 --- a/src/test/resources/taskRef_propagation_test_parent.xml +++ b/src/test/resources/taskRef_propagation_test_parent.xml @@ -1,211 +1,267 @@ - - + parent 1.0.0 - PAR parent home true - false - - - + false + + PAR + + + + + children_tasks + TaskRef + file File - + + multichoice + Multichoice + + + multichoice_setter + Multichoice Setter + + multichoice_setter_set + + + + + + + + + number + Number + text Text - - set - + text_set - - text: f.text, - children_tasks: f.children_tasks; - + + + ]]> + - - - text: f.text, - children_tasks: f.children_tasks; - + + + ]]> + - - - multichoice - Multichoice - - - - multichoice_setter - Multichoice Setter - - - multichoice_setter: f.multichoice_setter, - multichoice: f.multichoice; - - def newChoices = multichoice_setter.value.split(";") as List - change multichoice choices { newChoices } - - - - - number - Number - - - - children_tasks - TaskRef - - text_from_child Text from child - text_from_child_setter Text from child setter - - - text_from_child_setter: f.text_from_child_setter, - text_from_child: f.text_from_child; - - change text_from_child value { text_from_child_setter.value as String } - + + text_from_child_setter_set + + + + + + - - - 4 - 580 + t2 + 780 220 - + Task 2 auto - - - 0 - Edit - - file - - editable - - - - text - - editable - - - - text_from_child - - editable - - - - multichoice - - editable - - - - multichoice_setter - - editable - - - - - - 1 - Inštancie - - children_tasks - - editable - - - - - + + t2_flex + + + file + + editable + + + + 0 + 0 + 1 + + + + + text + + editable + + + + 0 + 0 + 1 + + + + + text_from_child + + editable + + + + 0 + 0 + 1 + + + + + multichoice + + editable + + + + 0 + 0 + 1 + + + + + multichoice_setter + + editable + + + + 0 + 0 + 1 + + + + + children_tasks + + editable + + + + 0 + 0 + 1 + + + - - 2 - 780 + t4 + 580 220 - + Task 1 auto - - - 0 - Edit - - file - - editable - - - - text - - editable - - - - text_from_child - - editable - - - - multichoice - - editable - - - - multichoice_setter - - editable - - - - - - 1 - Inštancie - - children_tasks - - editable - - - + + t4_flex + + + file + + editable + + + + 0 + 0 + 1 + + + + + text + + editable + + + + 0 + 0 + 1 + + + + + text_from_child + + editable + + + + 0 + 0 + 1 + + + + + multichoice + + editable + + + + 0 + 0 + 1 + + + + + multichoice_setter + + editable + + + + 0 + 0 + 1 + + + + + children_tasks + + editable + + + + 0 + 0 + 1 + + + - - - + \ No newline at end of file diff --git a/src/test/resources/task_authentication_service_test.xml b/src/test/resources/task_authentication_service_test.xml deleted file mode 100644 index 03e79da9421..00000000000 --- a/src/test/resources/task_authentication_service_test.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - 1 - TST - TaskAuthenticationService test - - role - role - - - text - Text - text - - - file - File - - - 1 - 1 - 1 - - - role - - true - - - - text - - editable - - - - file - - editable - - - - diff --git a/src/test/resources/task_authorization_service_test.xml b/src/test/resources/task_authorization_service_test.xml deleted file mode 100644 index 6662e550a5b..00000000000 --- a/src/test/resources/task_authorization_service_test.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - wst - WST - WorkflowAuthorizationService test - - assign_pos_role - assign pos role - - - assign_neg_role - assign neg role - - - finish_pos_role - finish pos role - - - finish_neg_role - finish neg role - - - text - Text - text - - - file - File - - - 1 - 1 - 1 - - - assign_pos_role - - true - - - - assign_neg_role - - false - - - - finish_pos_role - - true - - - - finish_neg_role - - false - - - - text - - editable - - - - file - - editable - - - - diff --git a/src/test/resources/task_authorization_service_test_with_userRefs.xml b/src/test/resources/task_authorization_service_test_with_userRefs.xml index 67ca0859531..245fe2f7c59 100644 --- a/src/test/resources/task_authorization_service_test_with_userRefs.xml +++ b/src/test/resources/task_authorization_service_test_with_userRefs.xml @@ -1,39 +1,40 @@ - - + wst_usersRef - WSU + 1.0.0 WorkflowAuthorizationService test + false + false + + WSU + + + - assign_pos_role - assign pos role + assign_neg_role + assign neg role - finish_pos_role - finish pos role + assign_pos_role + assign pos role - assign_neg_role - assign neg role + finish_neg_role + finish neg role - finish_neg_role - finish neg role + finish_pos_role + finish pos role - - assign_pos_ul - - </data> <data type="userList"> <id>assign_neg_ul</id> <title/> </data> <data type="userList"> - <id>delegate_pos_ul</id> + <id>assign_pos_ul</id> <title/> </data> <data type="userList"> - <id>delegate_neg_ul</id> + <id>cancel_neg_ul</id> <title/> </data> <data type="userList"> @@ -41,114 +42,111 @@ <title/> </data> <data type="userList"> - <id>cancel_neg_ul</id> + <id>delegate_neg_ul</id> <title/> </data> <data type="userList"> - <id>finish_pos_ul</id> + <id>delegate_pos_ul</id> <title/> </data> + <data type="file"> + <id>file</id> + <title>File + finish_neg_ul </data> + <data type="userList"> + <id>finish_pos_ul</id> + <title/> + </data> <data type="text"> <id>text</id> <title>Text text - - file - File - - 1 + t1 1 1 - - - assign_pos_role - - true - - + Transition assign_neg_role - + false - + - finish_pos_role - - true - + assign_neg_ul + + false + - finish_neg_role - - false - + assign_pos_role + + true + - + assign_pos_ul - + true - - - - assign_neg_ul - - false - - - - delegate_pos_ul - - true - - - - delegate_neg_ul - - false - - - - cancel_pos_ul - - true - - - + + + cancel_neg_ul - + false - - - - finish_pos_ul - - true - - - - finish_neg_ul - - false - - - - text - - editable - - - - file - - editable - - + + + + cancel_pos_ul + + true + + + + delegate_neg_ul + + false + + + + delegate_pos_ul + + true + + + + t1_flex + + + text + + editable + + + + 0 + 0 + 1 + + + + + file + + editable + + + + 0 + 0 + 1 + + + - + \ No newline at end of file diff --git a/src/test/resources/task_cancel_net.xml b/src/test/resources/task_cancel_net.xml deleted file mode 100644 index 7c4673e3a8f..00000000000 --- a/src/test/resources/task_cancel_net.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - test - TST - Test - - - worker - worker - - - manager - manager - - - - - test_text_file - Field 1 - - - - - 2 - 327 - 196 - - auto - - - worker - - true - - - - manager - - true - - - - - test_text_file - - editable - - - - - - - - 1 - 177 - 194 - - 1 - false - - - - - 4 - read - 1 - 2 - 1 - - - \ No newline at end of file diff --git a/src/test/resources/task_events.xml b/src/test/resources/task_events.xml index 41a9af46294..c06333b83f1 100644 --- a/src/test/resources/task_events.xml +++ b/src/test/resources/task_events.xml @@ -1,10 +1,14 @@ - - + test - TST + 1.0.0 Test true + false + + TST + + + field Field @@ -14,17 +18,19 @@ task 0 0 - + Task - 1 + task_finish - + + + ]]> + @@ -32,6 +38,6 @@ work_task 0 0 - + Work task - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/task_events_test.xml b/src/test/resources/task_events_test.xml deleted file mode 100644 index 7733ddecda6..00000000000 --- a/src/test/resources/task_events_test.xml +++ /dev/null @@ -1,356 +0,0 @@ - - - task_events_test - TTT - Task events test - true - false - - - - - - - pre_finish - Pre finish outcome - - - post_finish - Post finish outcome - - - pre_assign - Pre assign outcome - - - post_assign - Post finish outcome - - - pre_cancel - Pre cancel outcome - - - post_cancel - Post cancel outcome - - - pre_delegate - Pre delegate outcome - - - post_delegate - Post delegate outcome - - - interprocess_set_data - Interprocess set data outcome - - setdata - - - pre_set_data: f.pre_set_data; - - change pre_set_data value { "Result of pre SET DATA" } - - - - - post_set_data: f.post_set_data; - - change post_set_data value { "Result of post SET DATA" } - - - - - - pre_set_data - Pre set data outcome - - - post_set_data - Post set data outcome - - - - - t1 - 237 - 98 - - 0 - - - - DataGroup - grid - - pre_assign - - visible - - - 0 - 0 - 1 - 4 - 0 - - outline - - - - post_assign - - visible - - - 0 - 1 - 1 - 4 - 0 - - outline - - - - pre_cancel - - visible - - - 0 - 3 - 1 - 4 - 0 - - outline - - - - post_cancel - - visible - - - 0 - 4 - 1 - 4 - 0 - - outline - - - - pre_delegate - - visible - - - 0 - 6 - 1 - 4 - 0 - - outline - - - - post_delegate - - visible - - - 0 - 7 - 1 - 4 - 0 - - outline - - - - pre_finish - - visible - - - 0 - 9 - 1 - 4 - 0 - - outline - - - - post_finish - - visible - - - 0 - 10 - 1 - 4 - 0 - - outline - - - - interprocess_set_data - - visible - - - 0 - 12 - 1 - 4 - 0 - - outline - - - - pre_set_data - - visible - - - 0 - 13 - 1 - 4 - 0 - - outline - - - - post_set_data - - visible - - - 0 - 14 - 1 - 4 - 0 - - outline - - - - - assign - - - field: f.pre_assign; - - change field value {"Result of pre ASSIGN event"} - - - - - field: f.post_assign; - - change field value {"Result of post ASSIGN event"} - - - - - - cancel - - - field: f.pre_cancel; - - change field value {"Result of pre CANCEL event"} - - - - - field: f.post_cancel; - - change field value {"Result of post CANCEL event"} - - - - - - delegate - - - field: f.pre_delegate; - - change field value {"Result of pre DELEGATE event"} - - - - - field: f.post_delegate; - - change field value {"Result of post DELEGATE event"} - - - - - - finish - - - field: f.pre_finish; - - change field value {"Result of pre FINISH event"} - - - - - field: f.post_finish; - - change field value {"Result of post FINISH event"} - - - - - - - t2 - 240 - 215 - - 0 - - - - assign - - - def testCase = createCase("task_events_test", "Interprocess communication test case") - def testTask = findTask({ it.transitionId.eq("t1") & it.caseId.eq(testCase.stringId)}) - assignTask(testTask) - cancelTask(testTask) - assignTask(testTask) - setData("t1", testCase, [ - "interprocess_set_data": [ - "value": "Result of interprocess SET DATA", - "type" : "text", - ] - ]) - finishTask(testTask) - - - - - - - diff --git a/src/test/resources/task_ref_data.xml b/src/test/resources/task_ref_data.xml deleted file mode 100644 index 27dd2ac8919..00000000000 --- a/src/test/resources/task_ref_data.xml +++ /dev/null @@ -1,111 +0,0 @@ - - - task_ref_data - TRD - Task ref data - true - false - - - - - - - text_set_data - Reffed text dataField - - a - - - parent_task_id: f.parent_task_id; - - setData(findTask({ it.id.eq(parent_task_id.value as String) }), [ - "native_text": [ - "value": "Value changed from child task using normal setData", - "type": "text" - ], - "child_task_id_that_set_value": [ - "value": task.get().stringId, - "type": "text" - ] - ]) - - - - - - parent_set_data_result - Result of parent setting value by setDataWithPropagation - - - file - test file - - - parent_task_id - - - - - - t1 - 275 - 165 - - - 0 - - - DataGroup - grid - Task ref data - - text_set_data - - editable - - - 0 - 0 - 1 - 4 - 0 - - outline - - - - parent_set_data_result - - editable - - - 0 - 1 - 1 - 4 - 0 - - outline - - - - file - - editable - - - 0 - 2 - 1 - 4 - 0 - - outline - - - - - - - diff --git a/src/test/resources/task_ref_set_data_test.xml b/src/test/resources/task_ref_set_data_test.xml deleted file mode 100644 index 2c45d09b626..00000000000 --- a/src/test/resources/task_ref_set_data_test.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - task_ref_set_data_test - TRS - Task ref set data test - true - false - - - - - - - taskRef_0 - - - ref - - - taskRef_0: f.taskRef_0; - - if(taskRef_0.value == null || taskRef_0.value == []){ - List<String> taskIds = [] - def testCase = createCase("task_ref_data", "Task ref data case 1") - def testTask = findTask({ it.transitionId.eq("t1") & it.caseId.eq(testCase.stringId)}) - def thisTask = task.get() - setData("t1", testCase, [ - "parent_task_id": [ - "type": "text", - "value": thisTask.stringId - ] - ]) - taskIds.add(testTask.stringId) - testCase = createCase("task_ref_data", "Task ref data case 2") - testTask = findTask({ it.transitionId.eq("t1") & it.caseId.eq(testCase.stringId)}) - setData("t1", testCase, [ - "parent_task_id": [ - "type": "text", - "value": thisTask.stringId - ] - ]) - taskIds.add(testTask.stringId) - change taskRef_0 value { taskIds } - } - - - - - - native_text - Result of child setting value by setDataWithPropagation - - a - - - trans: t.t1, - native_text_2: f.native_text_2; - - make native_text_2, editable on trans when { true } - - - - - - native_text_2 - Native text used for setting data in child - - a - - - taskRef_0: f.taskRef_0, - child_task_id_that_set_value: f.child_task_id_that_set_value; - - def childTaskId = (taskRef_0.value as List<String>).stream().filter({taskId -> taskId != child_task_id_that_set_value.value as String}).findFirst().get() - setData(findTask({ it.id.eq(childTaskId as String) }), [ - "parent_set_data_result": [ - "value": "Value set from parent using normal setData", - "type": "text" - ] - ]) - - - - - - child_task_id_that_set_value - - - - - - t1 - 275 - 165 - - - 0 - - - DataGroup - grid - - taskRef_0 - - editable - - - 0 - 0 - 1 - 4 - 0 - - outline - - - - - native - Native text fields - - 0 - - - native_text - - visible - - - - native_text_2 - - visible - - - - - - - diff --git a/src/test/resources/task_reindex_test.xml b/src/test/resources/task_reindex_test.xml deleted file mode 100644 index 3b924d3d2ef..00000000000 --- a/src/test/resources/task_reindex_test.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - task_reindex_test - TST - task_reindex_test - - - - - - 2 - 460 - 220 - - - - 3 - 460 - 340 - - - - 5 - 340 - 140 - - - - 9 - 740 - 220 - - - - - 1 - 340 - 260 - - 1 - false - - - 4 - 620 - 220 - - 0 - false - - - - 6 - regular - 1 - 2 - 1 - - - 7 - regular - 1 - 3 - 1 - - - 8 - regular - 2 - 4 - 1 - - - 10 - regular - 4 - 9 - 1 - - \ No newline at end of file diff --git a/src/test/resources/taskref_demo.xml b/src/test/resources/taskref_demo.xml deleted file mode 100644 index 4e38bcf1359..00000000000 --- a/src/test/resources/taskref_demo.xml +++ /dev/null @@ -1,309 +0,0 @@ - - - taskref_demo - 1.0.0 - TRD - TaskRef demo - home - true - false - - - - 1 - Block - - - - taskref_selector - Referenced tasks - Select referenced tasks - Task 1 - Task 2 - Task 3 - - taskrefInput: f.taskref_selector, - taskref: f.taskref; - - def taskrefValue = [] - if (taskrefInput.value.defaultValue.contains("Task 1")) { - taskrefValue.push(getTaskId("2")) - } - if (taskrefInput.value.defaultValue.contains("Task 2")) { - taskrefValue.push(getTaskId("3")) - } - if (taskrefInput.value.defaultValue.contains("Task 3")) { - taskrefValue.push(getTaskId("4")) - } - - change taskref value {return taskrefValue} - - - - taskref - set label - placeholder - description - value - - - text1 - Field under task ref - This field is placed under the task ref field - - - textarea - Toggleable text area - area - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eget venenatis enim. Suspendisse eu eros - iaculis, rutrum massa vitae, eleifend magna. Vestibulum id tempus tortor. Donec tincidunt aliquet metus, ut - maximus quam elementum nec. In semper risus vitae urna rutrum, sed consequat urna tincidunt. Integer nec - nunc mi. Nam ultricies accumsan ornare. Quisque faucibus purus in metus mollis sagittis. Quisque in aliquam - lectus. Duis sagittis condimentum ipsum, quis venenatis metus fringilla non. - - - - btn_show - Show text area - - textarea: f.textarea, - trans: t.2; - - make textarea,visible on trans when {return true} - - - - btn_hide - Hide text area - - textarea: f.textarea, - trans: t.2; - - make textarea,hidden on trans when {return true} - - - - even - Is the number even? - YES - - - numberInput - Enter any number - 0 - - numberInput: f.numberInput, - parity: f.even; - - change parity value {return (((int)numberInput.value)%2 == 0 ? "YES" : "NO")} - - - - text2 - Nested task ref - This task contains a nested task ref - - - nested_taskref - Task ref with label - - - - - 1 - 340 - 260 - - - taskref_selector - - editable - - - 0 - 0 - 1 - 2 - - outline - - - - taskref - - editable - - - 0 - 1 - 1 - 4 - - outline - - - - text1 - - editable - - - 0 - 2 - 1 - 4 - - outline - - - - 1_assign - - - taskref: f.nested_taskref; - - change taskref value {return [getTaskId("3")]} - - - - - - 2 - 500 - 180 - - 1 - - true - - - - - textarea - - hidden - - - 0 - 1 - 2 - 4 - - outline - - - - btn_show - - editable - - - 0 - 0 - 1 - 2 - - - - - btn_hide - - editable - - - 2 - 0 - 1 - 2 - - - - - - 3 - 500 - 260 - - 1 - - true - - - - - even - - visible - - - 2 - 0 - 1 - 2 - - outline - - - - numberInput - - editable - - - 0 - 0 - 1 - 2 - - outline - - - - - 4 - 500 - 340 - - 1 - - true - - - - - text2 - - editable - - - 0 - 0 - 1 - 2 - - outline - - - - nested_taskref - - editable - - nested_taskref: f.nested_taskref, - trans : t.this; - make nested_taskref, visible on trans when { nested_taskref.value.empty } - - - - - 0 - 1 - 1 - 4 - - outline - - - - diff --git a/src/test/resources/taskref_init.xml b/src/test/resources/taskref_init.xml index 7adfa558b4d..54ca4abb506 100644 --- a/src/test/resources/taskref_init.xml +++ b/src/test/resources/taskref_init.xml @@ -1,16 +1,13 @@ - - + taskref_init_test - TIT + 1.0.0 Task ref init test net true - false - - - - - + false + + TIT + taskRef_0 @@ -30,45 +27,39 @@ <id>taskRef_3</id> <title/> </data> - <!-- I18NS --> - <!-- TRANSITIONS --> <transition> <id>t1</id> <x>340</x> <y>140</y> - <layout> - <offset>0</offset> - </layout> - <label></label> + <title/> + <flex> + <id>t1_flex</id> + </flex> </transition> <transition> <id>t2</id> <x>660</x> <y>140</y> - <layout> - <offset>0</offset> - </layout> - <label></label> + <title/> + <flex> + <id>t2_flex</id> + </flex> </transition> <transition> <id>t3</id> <x>340</x> <y>300</y> - <layout> - <offset>0</offset> - </layout> - <label></label> + <title/> + <flex> + <id>t3_flex</id> + </flex> </transition> - <!-- PLACES --> <place> <id>p1</id> <x>500</x> <y>140</y> - <label></label> <tokens>0</tokens> - <static>false</static> </place> - <!-- ARCS --> <arc> <id>a1</id> <type>regular</type> @@ -83,4 +74,4 @@ <destinationId>t2</destinationId> <multiplicity>1</multiplicity> </arc> -</document> +</process> \ No newline at end of file diff --git a/src/test/resources/test.xml b/src/test/resources/test.xml deleted file mode 100644 index 170e539af3c..00000000000 --- a/src/test/resources/test.xml +++ /dev/null @@ -1,124 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document> - <id>test</id> - <initials>TST</initials> - <title>Test - false - - 13 - Názov dokumentu - Názov dokumentu, ktorý je uvedený na obale - - - 14 - Kód dokumentu - Kód dokumentu, ktorý je uvedený na obale - - - 15 - Názov firmy - Názov firmy, ktorý je uvedený na obale - - - 1 - 140 - 111 - - 1 - false - - - 3 - 380 - 44 - - 0 - false - - - 4 - 390 - 162 - - 0 - false - - - 6 - 635 - 120 - - 0 - false - - - 5 - 509 - 113 - - - 15 - - - - 2 - 266 - 105 - - - 13 - - - - - - 14 - - - - - - - - 7 - regular - 1 - 2 - 1 - - - 8 - regular - 2 - 3 - 1 - - - 9 - regular - 2 - 4 - 1 - - - 10 - regular - 3 - 5 - 1 - - - 11 - regular - 4 - 5 - 1 - - - 12 - regular - 5 - 6 - 1 - - \ No newline at end of file diff --git a/src/test/resources/test_autocomplete_dynamic.xml b/src/test/resources/test_autocomplete_dynamic.xml index e4612ef6af3..246ee960bfd 100644 --- a/src/test/resources/test_autocomplete_dynamic.xml +++ b/src/test/resources/test_autocomplete_dynamic.xml @@ -1,46 +1,48 @@ - - + test_autocomplete_dynamic + 1.0.0 Autocomplete Dynamic Net - ADN autocomplete <component> - <name>autocomplete_dynamic</name> + <id>autocomplete_dynamic</id> </component> - <action trigger="set"> - <!-- @formatter:off --> - field: f.autocomplete; - if (fieldChanges.value) { - change field choices { - def value = field.value.value.toString() - return findCases { it.title.contains(value) }.collect({it.title}) - } - } - <!-- @formatter:on --> - </action> + <event type="set"> + <id>autocomplete_set</id> + <actions phase="post"> + <action type="value"> + <!-- @formatter:off --> + change autocomplete choices { + def value = autocomplete.rawValue.toString() + return findCases { it.title.contains(value) }.collect({it.title}) + } + <!-- @formatter:on --> + </action> + </actions> + </event> </data> <!-- TRANSITIONS --> <transition> - <id>3</id> + <id>t1</id> <x>379</x> <y>273</y> - <label>Autocomplete</label> + <title>Autocomplete auto - - auto - Autocomplete - false - - autocomplete - - editable - required - - - + + t1_flex + + + autocomplete + + editable + true + + + + - + diff --git a/src/test/resources/test_icon_enum.xml b/src/test/resources/test_icon_enum.xml deleted file mode 100644 index 957a2c96408..00000000000 --- a/src/test/resources/test_icon_enum.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - test_icon_enum - Icon Enum Net - IEN - - icon_enum - - <values>Krádež</values> - <values>Poškodenie Zariadenia</values> - <values>Rozbitie skla</values> - <values>Vandalizmus</values> - <values>Živelná škoda</values> - <component> - <name>icon</name> - <properties> - <property key="arrow">true</property> - <property key="divider">true</property> - <option_icons> - <icon key="Krádež">home</icon> - <icon key="Poškodenie Zariadenia">nature</icon> - <icon key="Rozbitie skla">home</icon> - <icon key="Vandalizmus">nature</icon> - <icon key="Živelná škoda">home</icon> - </option_icons> - </properties> - </component> - </data> - <data type="enumeration_map"> - <id>icon_enum_map</id> - <title/> - <options> - <option key="1">Krádež</option> - <option key="2">Poškodenie Zariadenia</option> - <option key="3">Rozbitie skla</option> - <option key="4">Vandalizmus</option> - <option key="5">Živelná škoda</option> - </options> - <component> - <name>icon</name> - <properties> - <option_icons> - <icon key="1">home</icon> - <icon key="2">nature</icon> - <icon key="3">home</icon> - <icon key="4">nature</icon> - <icon key="5">home</icon> - </option_icons> - </properties> - </component> - </data> - - <transition> - <id>3</id> - <x>379</x> - <y>273</y> - <label>Enum Icon</label> - <assignPolicy>auto</assignPolicy> - <dataGroup> - <id>enum</id> - <title>Enum - false - - icon_enum - - editable - - - icon - - - home - nature - home - nature - home - - - - - - icon_enum_map - - editable - - - - - diff --git a/src/test/resources/test_inter_data_actions_dynamic.xml b/src/test/resources/test_inter_data_actions_dynamic.xml index 43b188af49c..194e2b3061a 100644 --- a/src/test/resources/test_inter_data_actions_dynamic.xml +++ b/src/test/resources/test_inter_data_actions_dynamic.xml @@ -1,72 +1,95 @@ - - + test - TST + 1.0.0 Test true + false + + TST + + + - 1 + data1 Cost - - - cost: f.1; - execute "static_edit_limits" with ([ - "delta_limit": [ - value: cost.value, - type: "number", - ] - ] as Map) - - + + data1_set + + + + + + - 2 + data2 Available - 2 + t2 270 108 - - - 1 - Limits - - 1 - - editable - required - - - + T2 + + t2_flex + + + data1 + + editable + true + + + + 0 + 0 + 1 + + + dynamic_edit_available 100 100 - - - 2 - - editable - required - - + Edit available + + dynamic_edit_available_flex + + + data2 + + editable + true + + + + 0 + 0 + 1 + + + - 1 + p1 134 111 - + IN 1 - false - 3 + a3 regular - 1 - 2 + p1 + t2 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/test_inter_data_actions_static.xml b/src/test/resources/test_inter_data_actions_static.xml index fa1e6a4873b..4bf2e0ae986 100644 --- a/src/test/resources/test_inter_data_actions_static.xml +++ b/src/test/resources/test_inter_data_actions_static.xml @@ -1,88 +1,114 @@ - - - test_inter_data_actions_static.xml - TST + + test_inter_data_actions_static + 1.0.0 Test true + false + + TST + + + + + delta_limit + Delta limit + limit Limit 1000000 - - - limit: f.limit; - execute "dynamic_edit_available" with ([ - "2": [ - value: limit.value, - type: "number", - ], - ] as Map) - - - - - delta_limit - Delta limit + + limit_set + + + + + + - 2 + t2 300 220 - - - 1 - Limits - - limit - - editable - - - + T1 + + t2_flex + + + limit + + editable + + + + 0 + 0 + 1 + + + static_edit_limits 100 100 - - - delta_limit - - editable - required - - - limit: f.limit, - delta: f.delta_limit; - change limit about { - limit.value - delta.value; - } - - - - + Edit limits + + static_edit_limits_flex + + + delta_limit + + editable + true + + + delta_limit_id + + + + + + + + + 0 + 0 + 1 + + + - 1 + p1 180 220 - + IN 1 - false - 3 + a3 regular - 1 - 2 + p1 + t2 1 - 4 + a4 regular - 2 - 1 + t2 + p1 1 - \ No newline at end of file + \ No newline at end of file diff --git a/src/test/resources/test_setData.xml b/src/test/resources/test_setData.xml index 86fde7e4000..92a209ce324 100644 --- a/src/test/resources/test_setData.xml +++ b/src/test/resources/test_setData.xml @@ -1,117 +1,123 @@ - + test_setData - TSD + 1.0.0 TestSetData device_hub true true - false - - caseRef_1 - - </data> - <data type="enumeration_map"> - <id>enumeration_map_0</id> - <title/> - </data> - <data type="enumeration"> - <id>enumeration_0</id> - <title/> - </data> + <properties> + <property key="initials">TSD</property> + </properties> + <processEvents/> + <caseEvents/> <data type="button"> <id>button_0</id> <title/> <component> - <name>raised</name> + <id>raised</id> </component> </data> <data type="button"> <id>button_1</id> <title/> + <event type="set"> + <id>x0</id> + <actions phase="pre"> + <action> + button_0: f.button_0; + + change button_0 value { 1337 } + </action> + </actions> + </event> + </data> + <data type="caseRef"> + <id>caseRef_1</id> + <title/> + </data> + <data type="enumeration"> + <id>enumeration_0</id> + <title/> + </data> + <data type="enumeration_map"> + <id>enumeration_map_0</id> + <title/> </data> <transition> <id>t1</id> <x>340</x> <y>140</y> - <label/> - <dataGroup> - <id>t1_0</id> - <cols>4</cols> - <layout>grid</layout> - <dataRef> - <id>caseRef_1</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>0</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>enumeration_map_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>0</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>enumeration_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>0</x> - <y>1</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>button_0</id> - <logic> - <behavior>editable</behavior> - </logic> - <layout> - <x>2</x> - <y>1</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - </dataRef> - <dataRef> - <id>button_1</id> - <logic> - <behavior>editable</behavior> - - </logic> - <layout> - <x>0</x> - <y>2</y> - <rows>1</rows> - <cols>2</cols> - <template>material</template> - <appearance>outline</appearance> - </layout> - <component> - <name>stroked</name> - </component> - </dataRef> - </dataGroup> -</transition> -</document> + <title/> + <flex> + <id>t1_flex</id> + <item> + <dataRef> + <id>caseRef_1</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>enumeration_map_0</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>enumeration_0</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>button_0</id> + <logic> + <behavior>editable</behavior> + </logic> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + <item> + <dataRef> + <id>button_1</id> + <logic> + <behavior>editable</behavior> + </logic> + <component> + <id>stroked</id> + </component> + </dataRef> + <properties> + <order>0</order> + <flex-grow>0</flex-grow> + <flex-shrink>1</flex-shrink> + </properties> + </item> + </flex> + </transition> +</process> \ No newline at end of file diff --git a/src/test/resources/this_kw_test.xml b/src/test/resources/this_kw_test.xml deleted file mode 100644 index e556a6667ec..00000000000 --- a/src/test/resources/this_kw_test.xml +++ /dev/null @@ -1,74 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="https://petriflow.com/petriflow.schema.xsd"> - <id>this_kw_test</id> - <initials>TKW</initials> - <title>This keyword test net - true - false - - - - - - - text_field - - - ev - - - tester_text_field: f.tester_text_field, - tf: f.this; - change tester_text_field value { tf.rawValue } - - - - - - - tester_text_field - - - - - - t1 - 340 - 140 - - 0 - - - - DataGroup - grid - - text_field - - editable - - - 0 - 0 - 1 - 1 - 0 - - outline - - - - - t1_assign - - - text_field: f.text_field; - change text_field value { "Hello world!" } - - - - - - - \ No newline at end of file diff --git a/src/test/resources/transactional_task_event_test.xml b/src/test/resources/transactional_task_event_test.xml new file mode 100644 index 00000000000..5b65321c079 --- /dev/null +++ b/src/test/resources/transactional_task_event_test.xml @@ -0,0 +1,93 @@ + + transactional_task_event_test + 1.0.0 + Test + true + false + + TST + + + + + assignTest + 0 + 0 + Task + + assignTest_flex + + + x1 + + + + + + + + + + + + + + cancelTest + 0 + 0 + Task + + cancelTest_flex + + + x2 + + + + + + + + + + + + + + finishTest + 0 + 0 + Task + + finishTest_flex + + + x3 + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/user_list.xml b/src/test/resources/user_list.xml index 7f5c2234003..8396fdfebb3 100644 --- a/src/test/resources/user_list.xml +++ b/src/test/resources/user_list.xml @@ -1,26 +1,29 @@ - - + user_list + 1.0.0 User list - ULT - - users_1 - - + false + false + + ALT + + users_1 - + false true - - + + upload - + + + ]]> + @@ -28,19 +31,21 @@ create - - text: f.text; - + + + ]]> + pdf - + + + ]]> + @@ -49,16 +54,20 @@ Text text - + + users_1 + + </data> <transition> - <id>1</id> - <label>Title</label> - <usersRef> + <id>t1</id> + <x>0</x> + <y>0</y> + <title>Title + users_1 - + true - - + + - - + \ No newline at end of file diff --git a/src/test/resources/userrefs_test.xml b/src/test/resources/userrefs_test.xml index e2b0c67e704..1012c3148c6 100644 --- a/src/test/resources/userrefs_test.xml +++ b/src/test/resources/userrefs_test.xml @@ -1,38 +1,40 @@ - - + testing_model - TSM + 1.0.0 Testing Model false - false - - + false + + TSM + + + user_list_1 + + true + + + + - tester - Testing Role + admin + Admin Role enabledTester Enabled Testing Role - admin - Admin Role + tester + Testing Role - - - user_list_1 - - true - - - - - assign Assign to user ref + + email + Email + remove Remove from user ref @@ -45,98 +47,107 @@ user_list_2 User list 2 - - email - Email - - - t1 380 260 - - 0 - - + Initialization enabledTester - + true true - + - + user_list_1 - + true - - - - email - - editable - - - - assign - - editable - - - assign - - - userList: f.user_list_1, - email: f.email; - change userList value { [userService.findByEmail(email.value, true).id] } - - - - - - remove - - editable - - - remove - - - userList: f.user_list_1; - change userList value { [] } - - - - + + + + t1_flex + + + email + + editable + + + + 0 + 0 + 1 + + + + + assign + + editable + + + assign + + + + + + + + + 0 + 0 + 1 + + + + + remove + + editable + + + remove + + + + + + + + + 0 + 0 + 1 + + + t2 620 260 - - 0 - - + Finishing - p1 260 260 - + #init 1 - false p2 500 260 - + After initialization state 0 - false - a1 regular @@ -164,6 +175,9 @@ t2 p1 1 - 460140 + + 460 + 140 + - + \ No newline at end of file diff --git a/src/test/resources/variable_arc_test.xml b/src/test/resources/variable_arc_test.xml index 2c2426bf1a4..2ec7be9a648 100644 --- a/src/test/resources/variable_arc_test.xml +++ b/src/test/resources/variable_arc_test.xml @@ -1,469 +1,432 @@ - - - variable_arc_test.xml - TST + + variable_arc_test + 1.0.0 Test - - - - - + false + false + + TST + - regular_var - regular_var + number_field + regular_var_old 2 - reset_var - reset_var + inhib_var_field + inhib_var 2 - read_var + read_var_field read_var 2 - inhib_var - inhib_var + regular_var_field + regular_var + 2 + + + reset_var_field + reset_var 2 - - 5000 - regular_var_old - 2 - - - - regular_var - 340 - 140 - - 0 - - + add_tokens + 691 + 100 + add_tokens + + add_tokens_flex + - reset_var - 334 - 401 - - 0 - - + inhib + 323 + 593 + inhib + + inhib_flex + - read_var - 1100 - 357 - - 0 - - + inhib_place_ref + 322 + 760 + inhib_place_ref + + inhib_place_ref_flex + inhib_var 323 679 - - 0 - - + inhib_var + + inhib_var_flex + + + + out_place_ref_arc + 182 + 939 + out_place_ref_arc + + out_place_ref_arc_flex + + + + out_var_arc + 186 + 853 + out_var_arc + + out_var_arc_flex + + + + out_var_arc_old + 171 + 1057 + out_var_arc_old + + out_var_arc_old_flex + + + + read + 1100 + 260 + read + + read_flex + + + + read_place_ref + 1110 + 450 + read_place_ref + + read_place_ref_flex + + + + read_var + 1100 + 357 + read_var + + read_var_flex + regular 340 60 - - 0 - - + regular + + regular_flex + regular_place_ref 340 220 - - 0 - - + regular_place_ref + + regular_place_ref_flex + - reset + regular_place_ref_old + 844 + 692 + regular_place_ref_old + + regular_place_ref_old_flex + + + + regular_var 340 - 300 - - 0 - - + 140 + regular_var + + regular_var_flex + - reset_place_ref - 331 - 494 - - 0 - - + regular_var_old + 836 + 571 + regular_var_old + + regular_var_old_flex + - inhib - 323 - 593 - - 0 - - + remove_tokens + 943 + 100 + remove_tokens + + remove_tokens_flex + - inhib_place_ref - 322 - 760 - - 0 - - + reset + 340 + 300 + reset + + reset_flex + - read - 1100 - 260 - - 0 - - + reset_place_ref + 331 + 494 + reset_place_ref + + reset_place_ref_flex + - read_place_ref - 1110 - 450 - - 0 - - + reset_var + 334 + 401 + reset_var + + reset_var_flex + - - out_var_arc - 186 - 853 - - 0 - - - - - out_place_ref_arc - 182 - 939 - - 0 - - - - - add_tokens - 691 - 100 - - 0 - - - - - remove_tokens - 943 - 100 - - 0 - - - - - regular_var_old - 836 - 571 - - 0 - - - - - regular_place_ref_old - 844 - 692 - - 0 - - - - - out_var_arc_old - 171 - 1057 - - 0 - - - - - regular_var_start - 220 - 140 - + place_1500 + 820 + 100 + place_1500 2 - false - regular_var_res - 460 - 140 - + inhib_place_ref_res + 457 + 760 + inhib_place_ref_res 0 - false - reset_var_start - 214 - 400 - - 2 - false + inhib_place_ref_start + 199 + 763 + inhib_place_ref_start + 0 - read_var_start - 978 - 360 - - 2 - false + inhib_res + 454 + 590 + inhib_res + 0 + + + inhib_start + 203 + 594 + inhib_start + 0 + + + inhib_var_res + 452 + 679 + inhib_var_res + 0 inhib_var_start 200 681 - + inhib_var_start 0 - false - reset_var_res - 464 - 399 - + out_place_ref_arc_res + 456 + 941 + out_place_ref_arc_res 0 - false - read_var_res - 1262 - 355 - + out_var_arc_old_res + 451 + 1065 + out_var_arc_old_res 0 - false - inhib_var_res - 452 - 679 - + out_var_arc_res + 460 + 849 + out_var_arc_res 0 - false - regular_res - 460 - 60 - + read_place_ref_res + 1258 + 449 + read_place_ref_res 0 - false - regular_place_ref_res - 460 - 220 - + read_place_ref_start + 981 + 453 + read_place_ref_start + 2 + + + read_res + 1260 + 260 + read_res 0 - false - 1500 - 820 - 100 - - 2 - false + read_start + 980 + 260 + read_start + 1 - reset_res - 460 - 300 - + read_var_res + 1262 + 355 + read_var_res 0 - false - reset_place_ref_res - 454 - 492 - + read_var_start + 978 + 360 + read_var_start + 2 + + + regular_place_ref_old_res + 1000 + 691 + regular_place_ref_old_res 0 - false - regular_start - 220 - 60 - - 1 - false + regular_place_ref_old_start + 680 + 694 + regular_place_ref_old_start + 2 + + + regular_place_ref_res + 460 + 220 + regular_place_ref_res + 0 regular_place_ref_start 220 220 - + regular_place_ref_start 2 - false - reset_start + regular_res + 460 + 60 + regular_res + 0 + + + regular_start 220 - 300 - + 60 + regular_start 1 - false - reset_place_ref_start - 207 - 495 - + regular_var_old_res + 1005 + 569 + regular_var_old_res + 0 + + + regular_var_old_start + 681 + 572 + regular_var_old_start 2 - false - inhib_start - 203 - 594 - + regular_var_res + 460 + 140 + regular_var_res 0 - false - inhib_place_ref_start - 199 - 763 - - 0 - false + regular_var_start + 220 + 140 + regular_var_start + 2 - inhib_res + reset_place_ref_res 454 - 590 - + 492 + reset_place_ref_res 0 - false - inhib_place_ref_res - 457 - 760 - - 0 - false + reset_place_ref_start + 207 + 495 + reset_place_ref_start + 2 - read_start - 980 - 260 - - 1 - false + reset_res + 460 + 300 + reset_res + 0 - read_place_ref_start - 981 - 453 - - 2 - false + reset_start + 220 + 300 + reset_start + 1 - read_res - 1260 - 260 - + reset_var_res + 464 + 399 + reset_var_res 0 - false - read_place_ref_res - 1258 - 449 - - 0 - false - - - out_var_arc_res - 460 - 849 - - 0 - false - - - out_place_ref_arc_res - 456 - 941 - - 0 - false - - - regular_var_old_start - 681 - 572 - - 2 - false - - - regular_var_old_res - 1005 - 569 - - 0 - false - - - regular_place_ref_old_start - 680 - 694 - - 2 - false - - - regular_place_ref_old_res - 1000 - 691 - - 0 - false - - - out_var_arc_old_res - 451 - 1065 - - 0 - false - - + reset_var_start + 214 + 400 + reset_var_start + 2 + a1 regular @@ -471,66 +434,6 @@ regular 1 - - a2 - regular - regular_var_start - regular_var - 2 - regular_var - - - a3 - regular - regular_place_ref_start - regular_place_ref - 2 - 1500 - - - a4 - regular - regular - regular_res - 1 - - - a5 - regular - regular_var - regular_var_res - 1 - - - a6 - regular - regular_place_ref - regular_place_ref_res - 1 - - - a7 - reset - reset_start - reset - 1 - - - a8 - reset - reset_var_start - reset_var - 2 - reset_var - - - a9 - reset - reset_place_ref_start - reset_place_ref - 2 - 1500 - a10 regular @@ -564,16 +467,22 @@ inhibitor inhib_var_start inhib_var - 2 - inhib_var + + + a15 inhibitor inhib_place_ref_start inhib_place_ref - 2 - 1500 + + + a16 @@ -587,16 +496,22 @@ read read_var_start read_var - 2 - read_var + + + a18 read read_place_ref_start read_place_ref - 2 - 1500 + + + a19 @@ -605,6 +520,17 @@ read_res 1 + + a2 + regular + regular_var_start + regular_var + + + + a20 regular @@ -639,70 +565,149 @@ inhib_place_ref inhib_place_ref_res 1 - - - a25 - regular - out_var_arc - out_var_arc_res - 2 - regular_var - - - a26 - regular - out_place_ref_arc - out_place_ref_arc_res - 2 - 1500 - - - a27 - regular - add_tokens - 1500 - 800 - - - a28 - regular - 1500 - remove_tokens - 800 - - - a29 - variable - regular_var_old_start - regular_var_old - 5000 - - - a30 - regular - regular_var_old - regular_var_old_res - 1 - - - a31 - variable - regular_place_ref_old_start - regular_place_ref_old - 1500 - - - a32 - regular - regular_place_ref_old - regular_place_ref_old_res - 1 - - - a33 - variable - out_var_arc_old - out_var_arc_old_res - 5000 - - + + + a25 + regular + out_var_arc + out_var_arc_res + + + + + + a26 + regular + out_place_ref_arc + out_place_ref_arc_res + + + + + + a27 + regular + add_tokens + place_1500 + 800 + + + a28 + regular + place_1500 + remove_tokens + 800 + + + a29 + regular + regular_var_old_start + regular_var_old + + + + + + a3 + regular + regular_place_ref_start + regular_place_ref + + + + + + a30 + regular + regular_var_old + regular_var_old_res + 1 + + + a31 + regular + regular_place_ref_old_start + regular_place_ref_old + + + + + + a32 + regular + regular_place_ref_old + regular_place_ref_old_res + 1 + + + a33 + regular + out_var_arc_old + out_var_arc_old_res + + + + + + a4 + regular + regular + regular_res + 1 + + + a5 + regular + regular_var + regular_var_res + 1 + + + a6 + regular + regular_place_ref + regular_place_ref_res + 1 + + + a7 + reset + reset_start + reset + 1 + + + a8 + reset + reset_var_start + reset_var + + + + + + a9 + reset + reset_place_ref_start + reset_place_ref + + + + + \ No newline at end of file diff --git a/src/test/resources/view_permission_test.xml b/src/test/resources/view_permission_test.xml index 48271ca6241..115dfa968a1 100644 --- a/src/test/resources/view_permission_test.xml +++ b/src/test/resources/view_permission_test.xml @@ -1,67 +1,87 @@ - - + vpt - VPT + 1.0.0 ViewPermissionTest test true - - view_pos_role - - true - - + false + + VPT + view_neg_role - + false - + - + view_pos_role - view pos role - + + true + + view_neg_role - view neg role + view neg role + + view_pos_role + view pos role + + + file + File + text Text text - - file - File - - 1 + t1 1 1 - - - view_pos_role - - true - - + Transition view_neg_role - + false - + + + + view_pos_role + + true + - - text - - editable - - - - file - - editable - - + + t1_flex + + + text + + editable + + + + 0 + 0 + 1 + + + + + file + + editable + + + + 0 + 0 + 1 + + + - + \ No newline at end of file diff --git a/src/test/resources/view_permission_with_userRefs_test.xml b/src/test/resources/view_permission_with_userRefs_test.xml index adeea8ba535..023f558e0e4 100644 --- a/src/test/resources/view_permission_with_userRefs_test.xml +++ b/src/test/resources/view_permission_with_userRefs_test.xml @@ -1,99 +1,119 @@ - - + vpt_userRefs - VPT + 1.0.0 ViewPermissionTest test true + false + + VPT + + + view_neg_role + + false + + view_pos_role - + true - + - - view_neg_role - + + view_ul_neg + false - + - + view_ul_pos - + true - - - - view_ul_neg - - false - - + + - view_pos_role - view role + view_neg_role + view role - view_neg_role - view role + view_pos_role + view role - - view_ul_pos - - </data> - <data type="userList"> - <id>view_ul_neg</id> - <title/> + <data type="file"> + <id>file</id> + <title>File text Text text - - file - File + + view_ul_neg + + </data> + <data type="userList"> + <id>view_ul_pos</id> + <title/> </data> <transition> - <id>1</id> + <id>t1</id> <x>1</x> <y>1</y> - <label>Transition</label> + <title>Transition + + view_neg_role + + false + + view_pos_role - + true - + - - view_neg_role - + + view_ul_neg + false - + - + view_ul_pos - + true - - - - view_ul_neg - - false - - - - text - - editable - - - - file - - editable - - + + + + t1_flex + + + text + + editable + + + + 0 + 0 + 1 + + + + + file + + editable + + + + 0 + 0 + 1 + + + - + \ No newline at end of file diff --git a/src/test/resources/workflow_authorization_service_test.xml b/src/test/resources/workflow_authorization_service_test.xml deleted file mode 100644 index 0d690ed8723..00000000000 --- a/src/test/resources/workflow_authorization_service_test.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - wst - WST - WorkflowAuthorizationService test - - delete_pos_role - - true - - - - create_pos_role - - true - - - - delete_neg_role - - false - - - - create_neg_role - - false - - - - delete_pos_role - delete role - - - create_pos_role - create role - - - delete_neg_role - delete role - - - create_neg_role - create role - - - text - Text - text - - - file - File - - - 1 - 1 - 1 - - - text - - editable - - - - file - - editable - - - - diff --git a/src/test/resources/workflow_authorization_service_test_with_userRefs.xml b/src/test/resources/workflow_authorization_service_test_with_userRefs.xml deleted file mode 100644 index f88c05d6381..00000000000 --- a/src/test/resources/workflow_authorization_service_test_with_userRefs.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - wst_usersRef - WSU - WorkflowAuthorizationService test - - delete_pos_role - - true - - - - create_pos_role - - true - - - - delete_neg_role - - false - - - - create_neg_role - - false - - - - neg_user_list - - false - - - - pos_user_list - - true - - - - delete_pos_role - delete role - - - create_pos_role - create role - - - delete_neg_role - delete role - - - create_neg_role - create role - - - pos_user_list - - </data> - <data type="userList"> - <id>neg_user_list</id> - <title/> - </data> - <data type="text"> - <id>text</id> - <title>Text - text - - - file - File - - - 1 - 1 - 1 - - - text - - editable - - - - file - - editable - - - - diff --git a/src/test/resources/zaverecna_praca.xml b/src/test/resources/zaverecna_praca.xml deleted file mode 100644 index f8e40e4354c..00000000000 --- a/src/test/resources/zaverecna_praca.xml +++ /dev/null @@ -1,540 +0,0 @@ - - - zaverecna_praca.xml - TST - Test - - - 1 - Úplný názov práce - - - 2 - Začiatok riešenia - - - 3 - Dátum odovzdania - - - 4 - Vedúci práce - 1 - - - 5 - Práca je v Anglickom jazyku - - - 6 - Typ záverečnej práce - Bakalárska - Diplomová - Dizertačná - - - 7 - Záverečná práca - - - 8 - Posudok vedúceho práce - - - 9 - Oponent práce - 3 - - - 10 - Autor - 5 - - - - 1 - Vedúci - - - 2 - Garant - - - 3 - Oponent - - - 4 - Predseda komisie - - - 5 - Študent - - - - 1 - 60 - 220 - - 1 - false - - - 3 - 220 - 220 - - 0 - false - - - 16 - 380 - 220 - - 0 - false - - - 17 - 540 - 220 - - 0 - false - - - 18 - 700 - 220 - - 0 - false - - - 19 - 780 - 140 - - 0 - false - - - 20 - 780 - 300 - - 0 - false - - - 21 - 980 - 140 - - 0 - false - - - 22 - 1140 - 140 - - 0 - false - - - 23 - 1060 - 300 - - 0 - false - - - 24 - 1260 - 220 - - 0 - false - - - - 2 - 140 - 220 - - - 1 - - true - - - - 1 - - true - true - - - - 2 - - true - true - - - - 3 - - true - true - 8m - - - - 4 - - true - true - - - - 5 - - true - true - - - - 6 - - true - true - - - - - 4 - 300 - 220 - - - 2 - - true - - - - - 5 - 460 - 140 - - - 5 - - true - - - - 10 - - true - true - - - - - 6 - 460 - 260 - - - 1 - - true - - - - 10 - - true - - - - 10 - - true - - - - - 7 - 620 - 220 - - - 1 - - true - - - - 10 - - true - - - - 10 - - true - - - - - 9 - 900 - 140 - - - 1 - - true - - - - 9 - - true - true - - - - - 12 - 900 - 300 - - - 1 - - true - - - - 8 - - true - true - - - - 7 - - true - - - - - 13 - 1060 - 140 - - - 3 - - true - - - - - 14 - 1140 - 220 - - - 4 - - true - - - - - 41 - 780 - 220 - - - 5 - - true - - - - 7 - - true - true - - - - - - 26 - regular - 1 - 2 - 1 - - - 27 - regular - 2 - 3 - 1 - - - 28 - regular - 3 - 4 - 1 - - - 29 - regular - 4 - 16 - 1 - - - 33 - regular - 16 - 5 - 1 - - - 34 - regular - 5 - 17 - 1 - - - 35 - regular - 17 - 6 - 1 - - - 36 - regular - 6 - 16 - 1 - - - 37 - regular - 17 - 7 - 1 - - - 38 - regular - 7 - 18 - 1 - - - 42 - regular - 18 - 41 - 1 - - - 43 - regular - 41 - 19 - 1 - - - 44 - regular - 41 - 20 - 1 - - - 45 - regular - 19 - 9 - 1 - - - 46 - regular - 9 - 21 - 1 - - - 47 - regular - 21 - 13 - 1 - - - 48 - regular - 13 - 22 - 1 - - - 49 - regular - 22 - 14 - 1 - - - 50 - regular - 14 - 24 - 1 - - - 51 - regular - 20 - 12 - 1 - - - 52 - regular - 12 - 23 - 1 - - - 53 - regular - 23 - 14 - 1 - - \ No newline at end of file