001// -------------------------------------------------------------------------------- 002// Copyright 2002-2026 Echo Three, LLC 003// 004// Licensed under the Apache License, Version 2.0 (the "License"); 005// you may not use this file except in compliance with the License. 006// You may obtain a copy of the License at 007// 008// http://www.apache.org/licenses/LICENSE-2.0 009// 010// Unless required by applicable law or agreed to in writing, software 011// distributed under the License is distributed on an "AS IS" BASIS, 012// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013// See the License for the specific language governing permissions and 014// limitations under the License. 015// -------------------------------------------------------------------------------- 016 017package com.echothree.model.control.workflow.server.logic; 018 019import com.echothree.model.control.security.server.control.SecurityControl; 020import com.echothree.model.control.workflow.server.control.WorkflowControl; 021import com.echothree.model.data.party.common.pk.PartyPK; 022import com.echothree.model.data.party.server.factory.PartyFactory; 023import com.echothree.model.data.workflow.server.entity.WorkflowDestination; 024import com.echothree.model.data.workflow.server.entity.WorkflowEntrance; 025import com.echothree.util.common.message.ExecutionErrors; 026import com.echothree.util.server.message.ExecutionErrorAccumulator; 027import com.echothree.util.server.persistence.EntityPermission; 028import javax.enterprise.context.ApplicationScoped; 029import javax.inject.Inject; 030 031@ApplicationScoped 032public class WorkflowSecurityLogic { 033 034 @Inject 035 PartyFactory partyFactory; 036 037 @Inject 038 SecurityControl securityControl; 039 040 @Inject 041 WorkflowControl workflowControl; 042 043 protected WorkflowSecurityLogic() { 044 super(); 045 } 046 047 public boolean checkWorkflowEntranceAvailable(final WorkflowEntrance workflowEntrance, final PartyPK partyPK) { 048 var checkPassed = false; 049 050 if(workflowControl.countWorkflowEntrancePartyTypesByWorkflowEntrance(workflowEntrance) != 0) { 051 var party = partyFactory.getEntityFromPK(EntityPermission.READ_ONLY, partyPK); 052 var partyType = party.getLastDetail().getPartyType(); 053 var workflowEntrancePartyType = workflowControl.getWorkflowEntrancePartyType(workflowEntrance, partyType); 054 055 if(workflowEntrancePartyType != null) { 056 var workflowEntranceSecurityRoles = workflowControl.getWorkflowEntranceSecurityRolesByWorkflowEntrancePartyType(workflowEntrancePartyType); 057 058 if(workflowEntranceSecurityRoles.isEmpty()) { 059 // If there are no individual Security Roles, then pass it since the user is in a Party Type that was found. 060 checkPassed = true; 061 } else { 062 // Otherwise, check each individual Security Role. 063 for(var workflowEntranceSecurityRole : workflowEntranceSecurityRoles) { 064 if(securityControl.partySecurityRoleExists(partyPK, workflowEntranceSecurityRole.getSecurityRolePK())) { 065 // The Party has one of the required Security Roles, allow the transition and stop further checking. 066 checkPassed = true; 067 break; 068 } 069 } 070 } 071 } 072 } else { 073 // If there are no Workflow Entrance Party Types, then allow the transition. 074 checkPassed = true; 075 } 076 077 return checkPassed; 078 } 079 080 public boolean checkAddEntityToWorkflow(final ExecutionErrorAccumulator eea, final WorkflowEntrance workflowEntrance, final PartyPK modifiedBy) { 081 var checkPassed = checkWorkflowEntranceAvailable(workflowEntrance, modifiedBy); 082 083 if(!checkPassed) { 084 eea.addExecutionError(ExecutionErrors.WorkflowEntranceNotAllowed.name()); 085 } 086 087 return checkPassed; 088 } 089 090 public boolean checkWorkflowDestinationAvailable(final WorkflowDestination workflowDestination, final PartyPK partyPK) { 091 var checkPassed = false; 092 093 if(workflowControl.countWorkflowDestinationPartyTypes(workflowDestination) != 0) { 094 var party = partyFactory.getEntityFromPK(EntityPermission.READ_ONLY, partyPK); 095 var partyType = party.getLastDetail().getPartyType(); 096 var workflowDestinationPartyType = workflowControl.getWorkflowDestinationPartyType(workflowDestination, partyType); 097 098 if(workflowDestinationPartyType != null) { 099 var workflowDestinationSecurityRoles = workflowControl.getWorkflowDestinationSecurityRolesByWorkflowDestinationPartyType(workflowDestinationPartyType); 100 101 if(workflowDestinationSecurityRoles.isEmpty()) { 102 // If there are no individual Security Roles, then pass it since the user is in a Party Type that was found. 103 checkPassed = true; 104 } else { 105 // Otherwise, check each individual Security Role. 106 for(var workflowDestinationSecurityRole : workflowDestinationSecurityRoles) { 107 if(securityControl.partySecurityRoleExists(partyPK, workflowDestinationSecurityRole.getSecurityRolePK())) { 108 // The Party has one of the required Security Roles, allow the transition and stop further checking. 109 checkPassed = true; 110 break; 111 } 112 } 113 } 114 } 115 } else { 116 // If there are no Workflow Destination Party Types, then allow the transition. 117 checkPassed = true; 118 } 119 120 return checkPassed; 121 } 122 123 public boolean checkTransitionEntityInWorkflow(final ExecutionErrorAccumulator eea, final WorkflowDestination workflowDestination, final PartyPK modifiedBy) { 124 var checkPassed = checkWorkflowDestinationAvailable(workflowDestination, modifiedBy); 125 126 if(!checkPassed) { 127 eea.addExecutionError(ExecutionErrors.WorkflowDestinationNotAllowed.name()); 128 } 129 130 return checkPassed; 131 } 132 133}